feat: original commit of the files

This commit is contained in:
ALittlePatate
2022-09-30 14:34:24 +02:00
commit 45d39d6e64
114 changed files with 51222 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
.vs
.git
x64
todo.txt
DevourClient/x64

25
DevourClient.sln Normal file
View File

@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.1.32407.343
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DevourClient", "DevourClient\DevourClient.vcxproj", "{C7CBEBBD-CEF6-40C5-B6F5-2098545BB8A5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C7CBEBBD-CEF6-40C5-B6F5-2098545BB8A5}.Debug|x64.ActiveCfg = Debug|x64
{C7CBEBBD-CEF6-40C5-B6F5-2098545BB8A5}.Debug|x64.Build.0 = Debug|x64
{C7CBEBBD-CEF6-40C5-B6F5-2098545BB8A5}.Release|x64.ActiveCfg = Release|x64
{C7CBEBBD-CEF6-40C5-B6F5-2098545BB8A5}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {654219AA-AB13-4E5C-926A-7F2F21E4310B}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,12 @@
#include "OnUpdate.hpp"
#include "../Utils/Settings/Settings.hpp"
#include "../Dependencies/IL2CPP_Resolver/il2cpp_resolver.hpp"
#include "../Utils/Players/Players.hpp"
#include <iostream>
void OnUpdate() {
if (settings::big_flashlight) {
}
}

View File

@@ -0,0 +1,2 @@
#pragma once
void OnUpdate();

View File

@@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto

View File

@@ -0,0 +1,74 @@
#include "Includes.hpp"
namespace IL2CPP
{
namespace SystemTypeCache
{
class CCache
{
public:
unsigned int m_uHash = 0U;
Unity::il2cppObject* m_pSystemType = nullptr;
CCache() { }
CCache(unsigned int m_uKey, Unity::il2cppObject* m_pValue)
{
m_uHash = m_uKey;
m_pSystemType = m_pValue;
}
};
std::vector<CCache> m_vCache;
void Add(unsigned int m_uHash, Unity::il2cppObject* m_pSystemType)
{
if (!m_pSystemType)
return;
m_vCache.emplace_back(CCache(m_uHash, m_pSystemType));
}
void Add(const char* m_pName, Unity::il2cppObject* m_pSystemType)
{
if (!m_pName)
return;
Add(Utils::JOAAT(m_pName), m_pSystemType);
}
Unity::il2cppObject* Find(unsigned int m_uHash)
{
size_t m_sSize = m_vCache.size();
if (m_sSize > 0)
{
CCache* m_pData = m_vCache.data();
for (size_t i = 0; m_sSize > i; ++i)
{
if (m_pData[i].m_uHash == m_uHash)
return m_pData[i].m_pSystemType;
}
}
return nullptr;
}
Unity::il2cppObject* Find(const char* m_pName)
{
return Find(Utils::JOAAT(m_pName));
}
namespace Initializer
{
std::vector<const char*> m_vList;
void Add(const char* m_pName) { m_vList.emplace_back(m_pName); }
void PreCache()
{
for (const char* m_pName : m_vList)
SystemTypeCache::Add(m_pName, IL2CPP::Class::GetSystemType(m_pName));
m_vList.clear();
}
}
}
}

View File

@@ -0,0 +1,27 @@
#pragma once
namespace IL2CPP
{
namespace SystemTypeCache
{
void Add(unsigned int m_uHash, Unity::il2cppObject* m_pSystemType);
void Add(const char* m_pName, Unity::il2cppObject* m_pSystemType);
Unity::il2cppObject* Find(unsigned int m_uHash);
Unity::il2cppObject* Find(const char* m_pName);
namespace Initializer
{
extern std::vector<const char*> m_vList;
/*
* (WARNING) this needs to be called before actual IL2CPP Resolver Init, otherwise use function Add outside Initializer namespace!
*/
void Add(const char* m_pName);
void PreCache();
}
}
}

View File

@@ -0,0 +1,3 @@
#include "Includes.hpp"
namespace IL2CPP { SData Data; }

View File

@@ -0,0 +1,32 @@
#pragma once
namespace IL2CPP
{
struct SData
{
HMODULE m_hGameAseembly = 0;
struct SFunctions
{
void* m_pClassFromName = nullptr;
void* m_pClassGetFields = nullptr;
void* m_pClassGetFieldFromName = nullptr;
void* m_pClassGetMethods = nullptr;
void* m_pClassGetMethodFromName = nullptr;
void* m_pClassGetPropertyFromName = nullptr;
void* m_pClassGetType = nullptr;
void* m_pDomainGet = nullptr;
void* m_pDomainGetAssemblies = nullptr;
void* m_pFree = nullptr;
void* m_pImageGetClass = nullptr;
void* m_pImageGetClassCount = nullptr;
void* m_pResolveFunction = nullptr;
void* m_pStringNew = nullptr;
void* m_pThreadAttach = nullptr;
void* m_pThreadDetach = nullptr;
void* m_pTypeGetObject = nullptr;
};
SFunctions Functions;
};
extern SData Data;
}

View File

@@ -0,0 +1,32 @@
#pragma once
// Disable Asserts
//#define IL2CPP_ASSERT(x) assert(0)
#ifndef IL2CPP_ASSERT
#define IL2CPP_ASSERT(x) assert(x)
#endif
#ifndef IL2CPP_MAIN_MODULE
#define IL2CPP_MAIN_MODULE "GameAssembly.dll"
#endif
#define IL2CPP_INIT_EXPORT "il2cpp_init"
#define IL2CPP_CLASS_FROM_NAME_EXPORT "il2cpp_class_from_name"
#define IL2CPP_CLASS_GET_FIELDS "il2cpp_class_get_fields"
#define IL2CPP_CLASS_GET_FIELD_FROM_NAME_EXPORT "il2cpp_class_get_field_from_name"
#define IL2CPP_CLASS_GET_METHODS "il2cpp_class_get_methods"
#define IL2CPP_CLASS_GET_METHOD_FROM_NAME_EXPORT "il2cpp_class_get_method_from_name"
#define IL2CPP_CLASS_GET_PROPERTY_FROM_NAME_EXPORT "il2cpp_class_get_property_from_name"
#define IL2CPP_CLASS_GET_TYPE_EXPORT "il2cpp_class_get_type"
#define IL2CPP_DOMAIN_GET_EXPORT "il2cpp_domain_get"
#define IL2CPP_DOMAIN_GET_ASSEMBLIES_EXPORT "il2cpp_domain_get_assemblies"
#define IL2CPP_FREE_EXPORT "il2cpp_free"
#define IL2CPP_IMAGE_GET_CLASS_EXPORT "il2cpp_image_get_class"
#define IL2CPP_IMAGE_GET_CLASS_COUNT_EXPORT "il2cpp_image_get_class_count"
#define IL2CPP_RESOLVE_FUNC_EXPORT "il2cpp_resolve_icall"
#define IL2CPP_STRING_NEW_EXPORT "il2cpp_string_new"
#define IL2CPP_THREAD_ATTACH_EXPORT "il2cpp_thread_attach"
#define IL2CPP_THREAD_DETACH_EXPORT "il2cpp_thread_detach"
#define IL2CPP_TYPE_GET_OBJECT_EXPORT "il2cpp_type_get_object"
// Calling Convention
#define IL2CPP_CALLING_CONVENTION __fastcall*

View File

@@ -0,0 +1,86 @@
#include "../Includes.hpp"
namespace IL2CPP
{
namespace Callback
{
struct _VFuncCallback
{
std::vector<void*> m_vFunctions;
void** m_pVTable = nullptr;
void* m_pOriginal = nullptr;
};
namespace OnUpdate
{
_VFuncCallback Data;
void Add(void* m_pFunction) { Data.m_vFunctions.emplace_back(m_pFunction); }
void __fastcall Caller(void* rcx)
{
for (void* m_pFunction : Data.m_vFunctions)
reinterpret_cast<void(*)()>(m_pFunction)();
reinterpret_cast<void(__fastcall*)(void*)>(Data.m_pOriginal)(rcx);
}
}
namespace OnLateUpdate
{
_VFuncCallback Data;
void Add(void* m_pFunction) { Data.m_vFunctions.emplace_back(m_pFunction); }
void __fastcall Caller(void* rcx)
{
for (void* m_pFunction : Data.m_vFunctions)
reinterpret_cast<void(*)()>(m_pFunction)();
reinterpret_cast<void(__fastcall*)(void*)>(Data.m_pOriginal)(rcx);
}
}
void Replace_VFunc(void** m_pVTableFunc, void* m_pCaller, void** m_pCallbackOriginal)
{
DWORD m_dOldProtection = 0x0;
if (m_pVTableFunc && VirtualProtect(m_pVTableFunc, sizeof(void*), PAGE_READWRITE, &m_dOldProtection))
{
if (m_pCallbackOriginal) *m_pCallbackOriginal = *m_pVTableFunc;
*m_pVTableFunc = m_pCaller;
VirtualProtect(m_pVTableFunc, sizeof(void*), m_dOldProtection, &m_dOldProtection);
}
}
void Initialize()
{
void* m_pThread = IL2CPP::Thread::Attach(IL2CPP::Domain::Get());
// Fetch
{
void** m_pMonoBehaviourVTable = *reinterpret_cast<void***>(IL2CPP::Helper::GetMonoBehaviour()->m_CachedPtr);
if (m_pMonoBehaviourVTable) // x86: darkness my old friend
{
OnUpdate::Data.m_pVTable = VFunc::Find_ASM(m_pMonoBehaviourVTable, 99, { 0x33, 0xD2, 0xE9 }); // xor edx, edx | jmp
OnLateUpdate::Data.m_pVTable = VFunc::Find_ASM(m_pMonoBehaviourVTable, 99, { 0xBA, 0x01, 0x00, 0x00, 0x00, 0xE9 }); // mov edx, 1 | jmp
}
}
IL2CPP::Thread::Detach(m_pThread);
// Replace
{
Replace_VFunc(OnUpdate::Data.m_pVTable, OnUpdate::Caller, &OnUpdate::Data.m_pOriginal);
Replace_VFunc(OnLateUpdate::Data.m_pVTable, OnLateUpdate::Caller, &OnLateUpdate::Data.m_pOriginal);
}
}
void Uninitialize()
{
Replace_VFunc(OnUpdate::Data.m_pVTable, OnUpdate::Data.m_pOriginal, nullptr);
Replace_VFunc(OnLateUpdate::Data.m_pVTable, OnLateUpdate::Data.m_pOriginal, nullptr);
}
}
}

View File

@@ -0,0 +1,21 @@
#pragma once
namespace IL2CPP
{
namespace Callback
{
namespace OnUpdate
{
void Add(void* m_pFunction);
}
namespace OnLateUpdate
{
void Add(void* m_pFunction);
}
void Initialize();
void Uninitialize();
}
}

View File

@@ -0,0 +1,289 @@
#include "../Includes.hpp"
namespace IL2CPP
{
namespace Class
{
Unity::il2cppFieldInfo* GetFields(Unity::il2cppClass* m_pClass, void** m_pIterator)
{
return reinterpret_cast<Unity::il2cppFieldInfo*(IL2CPP_CALLING_CONVENTION)(void*, void**)>(Data.Functions.m_pClassGetFields)(m_pClass, m_pIterator);
}
void FetchFields(Unity::il2cppClass* m_pClass, std::vector<Unity::il2cppFieldInfo*>* m_pVector, void* m_pFieldIterator)
{
m_pVector->clear();
while (1)
{
Unity::il2cppFieldInfo* m_pField = GetFields(m_pClass, &m_pFieldIterator);
if (!m_pField)
break;
m_pVector->emplace_back(m_pField);
}
}
Unity::il2cppMethodInfo* GetMethods(Unity::il2cppClass* m_pClass, void** m_pIterator)
{
return reinterpret_cast<Unity::il2cppMethodInfo*(IL2CPP_CALLING_CONVENTION)(void*, void**)>(Data.Functions.m_pClassGetMethods)(m_pClass, m_pIterator);
}
void FetchMethods(Unity::il2cppClass* m_pClass, std::vector<Unity::il2cppMethodInfo*>* m_pVector, void* m_pMethodIterator)
{
m_pVector->clear();
while (1)
{
Unity::il2cppMethodInfo* m_pMethod = GetMethods(m_pClass, &m_pMethodIterator);
if (!m_pMethod)
break;
m_pVector->emplace_back(m_pMethod);
}
}
Unity::il2cppType* GetType(Unity::il2cppClass* m_pClass)
{
return reinterpret_cast<Unity::il2cppType*(IL2CPP_CALLING_CONVENTION)(void*)>(Data.Functions.m_pClassGetType)(m_pClass);
}
Unity::il2cppObject* GetSystemType(Unity::il2cppClass* m_pClass)
{
return reinterpret_cast<Unity::il2cppObject*(IL2CPP_CALLING_CONVENTION)(void*)>(Data.Functions.m_pTypeGetObject)(GetType(m_pClass));
}
Unity::il2cppObject* GetSystemType(const char* m_pClassName)
{
Unity::il2cppClass* m_pClass = Find(m_pClassName);
if (!m_pClass)
return nullptr;
return GetSystemType(m_pClass);
}
Unity::il2cppClass* GetFromName(Unity::il2cppImage* m_pImage, const char* m_pNamespace, const char* m_pName)
{
return reinterpret_cast<Unity::il2cppClass*(IL2CPP_CALLING_CONVENTION)(void*, const char*, const char*)>(Data.Functions.m_pClassFromName)(m_pImage, m_pNamespace, m_pName);
}
Unity::il2cppClass* Find(const char* m_pName)
{
size_t m_sAssembliesCount = 0U;
Unity::il2cppAssembly** m_pAssemblies = Domain::GetAssemblies(&m_sAssembliesCount);
if (!m_pAssemblies || 0U >= m_sAssembliesCount) return nullptr;
const char* m_pNameSpaceEnd = strrchr(m_pName, '.');
char* m_pNameSpace = nullptr;
if (m_pNameSpaceEnd)
{
uintptr_t m_uNamespaceSize = static_cast<uintptr_t>(m_pNameSpaceEnd - m_pName);
m_pNameSpace = new char[m_uNamespaceSize + 1];
memcpy(m_pNameSpace, m_pName, m_uNamespaceSize);
m_pNameSpace[m_uNamespaceSize] = '\0';
m_pName = m_pNameSpaceEnd + 1;
}
else
{
m_pNameSpace = new char[2];
memset(m_pNameSpace, 0, 2);
}
Unity::il2cppClass* m_pClassReturn = nullptr;
for (size_t i = 0U; m_sAssembliesCount > i; ++i)
{
Unity::il2cppAssembly* m_pAssembly = m_pAssemblies[i];
if (!m_pAssembly || !m_pAssembly->m_pImage) continue;
m_pClassReturn = GetFromName(m_pAssembly->m_pImage, m_pNameSpace, m_pName);
if (m_pClassReturn) break;
}
delete[] m_pNameSpace;
return m_pClassReturn;
}
void FetchClasses(std::vector<Unity::il2cppClass*>* m_pVector, const char* m_pModuleName, const char* m_pNamespace)
{
m_pVector->clear();
size_t m_sAssembliesCount = 0U;
Unity::il2cppAssembly** m_pAssemblies = Domain::GetAssemblies(&m_sAssembliesCount);
if (!m_pAssemblies || 0U >= m_sAssembliesCount) return;
Unity::il2cppImage* m_pImage = nullptr;
for (size_t i = 0U; m_sAssembliesCount > i; ++i)
{
Unity::il2cppAssembly* m_pAssembly = m_pAssemblies[i];
if (!m_pAssembly || !m_pAssembly->m_pImage || strcmp(m_pAssembly->m_pImage->m_pNameNoExt, m_pModuleName) != 0)
continue;
m_pImage = m_pAssembly->m_pImage;
break;
}
if (m_pImage)
{
size_t m_sClassesCount = reinterpret_cast<size_t(IL2CPP_CALLING_CONVENTION)(void*)>(Data.Functions.m_pImageGetClassCount)(m_pImage);
for (size_t i = 0U; m_sClassesCount > i; ++i)
{
Unity::il2cppClass* m_pClass = reinterpret_cast<Unity::il2cppClass*(IL2CPP_CALLING_CONVENTION)(void*, size_t)>(Data.Functions.m_pImageGetClass)(m_pImage, i);
if (m_pNamespace)
{
if (m_pNamespace[0] == '\0')
{
if (m_pClass->m_pNamespace[0] != '\0')
continue;
}
else if (strcmp(m_pClass->m_pNamespace, m_pNamespace) != 0)
continue;
}
m_pVector->emplace_back(m_pClass);
}
}
}
namespace Utils
{
int GetFieldOffset(Unity::il2cppClass* m_pClass, const char* m_pName)
{
void* m_pFieldIterator = nullptr;
while (1)
{
Unity::il2cppFieldInfo* m_pField = GetFields(m_pClass, &m_pFieldIterator);
if (!m_pField)
break;
if (strcmp(m_pField->m_pName, m_pName) == 0)
return m_pField->m_iOffset;
}
return -1;
}
int GetFieldOffset(const char* m_pClassName, const char* m_pName)
{
Unity::il2cppClass* m_pClass = Find(m_pClassName);
if (m_pClass)
return GetFieldOffset(m_pClass, m_pName);
return -1;
}
void* GetMethodPointer(Unity::il2cppClass* m_pClass, const char* m_pMethodName, int m_iArgs)
{
Unity::il2cppMethodInfo* pMethod = reinterpret_cast<Unity::il2cppMethodInfo*(IL2CPP_CALLING_CONVENTION)(void*, const char*, int)>(Data.Functions.m_pClassGetMethodFromName)(m_pClass, m_pMethodName, m_iArgs);
if (!pMethod) return nullptr;
return pMethod->m_pMethodPointer;
}
void* GetMethodPointer(const char* m_pClassName, const char* m_pMethodName, int m_iArgs)
{
Unity::il2cppClass* m_pClass = Find(m_pClassName);
if (m_pClass)
return GetMethodPointer(m_pClass, m_pMethodName, m_iArgs);
return nullptr;
}
void* GetMethodPointer(const char* m_pClassName, const char* m_pMethodName, std::initializer_list<const char*> m_vNames)
{
Unity::il2cppClass* m_pClass = Find(m_pClassName);
if (!m_pClass)
return nullptr;
int m_iNamesCount = static_cast<int>(m_vNames.size());
const char** m_pNames = const_cast<const char**>(m_vNames.begin());
void* m_pMethodIterator = nullptr;
while (1)
{
Unity::il2cppMethodInfo* m_pMethod = GetMethods(m_pClass, &m_pMethodIterator);
if (!m_pMethod)
break;
if (strcmp(m_pMethod->m_pName, m_pMethodName) != 0)
continue;
Unity::il2cppParameterInfo* m_pCurrentParameters = m_pMethod->m_pParameters;
for (int i = 0; m_iNamesCount > i; ++i)
{
if (strcmp(m_pCurrentParameters->m_pName, m_pNames[i]) != 0)
break;
m_pCurrentParameters++; // m_pCurrentParameters += sizeof(Unity::il2cppParameterInfo);
if ((i + 1) == m_iNamesCount)
return m_pMethod->m_pMethodPointer;
}
}
return nullptr;
}
Unity::il2cppClass* FilterClass(std::vector<Unity::il2cppClass*>* m_pClasses, std::initializer_list<const char*> m_vNames, int m_iFoundCount)
{
int m_iNamesCount = static_cast<int>(m_vNames.size());
const char** m_pNames = const_cast<const char**>(m_vNames.begin());
if (0 >= m_iFoundCount || m_iFoundCount > m_iNamesCount)
m_iFoundCount = m_iNamesCount;
Unity::il2cppClass* m_pReturn = nullptr;
for (size_t c = 0; m_pClasses->size() > c; ++c)
{
int m_iFoundCountNow = 0;
Unity::il2cppClass* m_pClass = m_pClasses->operator[](c);
if (!m_pClass)
continue;
for (int i = 0; m_iNamesCount > i; ++i)
{
const char* m_pNameToFind = m_pNames[i];
bool m_bFoundInClass = false;
if (m_pNameToFind[0] == '~') // Field
m_bFoundInClass = GetFieldOffset(m_pClass, &m_pNameToFind[1]) >= 0;
else if (m_pNameToFind[0] == '-') // Method
m_bFoundInClass = GetMethodPointer(m_pClass, &m_pNameToFind[1]) != nullptr;
else // Both
{
m_bFoundInClass = GetFieldOffset(m_pClass, m_pNameToFind) >= 0;
if (!m_bFoundInClass)
m_bFoundInClass = GetMethodPointer(m_pClass, m_pNameToFind) != nullptr;
}
if (m_bFoundInClass)
++m_iFoundCountNow;
}
if (m_iFoundCount == m_iFoundCountNow)
{
m_pReturn = m_pClass;
break;
}
}
return m_pReturn;
}
void* FilterClassToMethodPointer(std::vector<Unity::il2cppClass*>* m_pClasses, const char* m_pMethodName, int m_iArgs)
{
void* m_pMethodPointer = nullptr;
for (size_t c = 0; m_pClasses->size() > c; ++c)
{
Unity::il2cppClass* m_pClass = m_pClasses->operator[](c);
if (!m_pClass)
continue;
m_pMethodPointer = GetMethodPointer(m_pClass, m_pMethodName, m_iArgs);
if (m_pMethodPointer)
break;
}
return m_pMethodPointer;
}
}
}
}

View File

@@ -0,0 +1,317 @@
#pragma once
namespace IL2CPP
{
namespace Class
{
Unity::il2cppFieldInfo* GetFields(Unity::il2cppClass* m_pClass, void** m_pIterator);
void FetchFields(Unity::il2cppClass* m_pClass, std::vector<Unity::il2cppFieldInfo*>* m_pVector, void* m_pFieldIterator = nullptr);
Unity::il2cppMethodInfo* GetMethods(Unity::il2cppClass* m_pClass, void** m_pIterator);
void FetchMethods(Unity::il2cppClass* m_pClass, std::vector<Unity::il2cppMethodInfo*>* m_pVector, void* m_pMethodIterator = nullptr);
Unity::il2cppType* GetType(Unity::il2cppClass* m_pClass);
Unity::il2cppObject* GetSystemType(Unity::il2cppClass* m_pClass);
Unity::il2cppObject* GetSystemType(const char* m_pClassName);
Unity::il2cppClass* GetFromName(Unity::il2cppImage* m_pImage, const char* m_pNamespace, const char* m_pName);
Unity::il2cppClass* Find(const char* m_pName);
/*
* If you wanna fetch modules with custom classes use modulename: Assembly-CSharp
* Nullptr namespace == pass any namespace
*/
void FetchClasses(std::vector<Unity::il2cppClass*>* m_pVector, const char* m_pModuleName, const char* m_pNamespace);
namespace Utils
{
int GetFieldOffset(Unity::il2cppClass* m_pClass, const char* m_pName);
int GetFieldOffset(const char* m_pClassName, const char* m_pName);
void* GetMethodPointer(Unity::il2cppClass* m_pClass, const char* m_pMethodName, int m_iArgs = -1);
void* GetMethodPointer(const char* m_pClassName, const char* m_pMethodName, int m_iArgs = -1);
/*
* Usage:
* m_vNames = { "arg1" , "arg2" , ... }
*/
void* GetMethodPointer(const char* m_pClassName, const char* m_pMethodName, std::initializer_list<const char*> m_vNames);
/*
* Name Prefixes
* (Field) ~
* (Method) -
*/
Unity::il2cppClass* FilterClass(std::vector<Unity::il2cppClass*>* m_pClasses, std::initializer_list<const char*> m_vNames, int m_iFoundCount = -1);
void* FilterClassToMethodPointer(std::vector<Unity::il2cppClass*>* m_pClasses, const char* m_pMethodName, int m_iArgs = -1);
}
}
enum class m_eClassPropType : int
{
Unknown = 0,
Field, // Member of class that can be accessed directly by RVA
Property, // Member of class that can be accessed by calling function
Method, // Function of class
};
class CClass
{
public:
Unity::il2cppObject m_Object = { 0 };
void* m_CachedPtr = nullptr;
// Wrappers for namespace, ah...
Unity::il2cppFieldInfo* GetFields(void** m_pIterator)
{
return Class::GetFields(m_Object.m_pClass, m_pIterator);
}
void FetchFields(std::vector<Unity::il2cppFieldInfo*>* m_pVector, void* m_pFieldIterator = nullptr)
{
Class::FetchFields(m_Object.m_pClass, m_pVector, m_pFieldIterator);
}
Unity::il2cppMethodInfo* GetMethods(void** m_pIterator)
{
return Class::GetMethods(m_Object.m_pClass, m_pIterator);
}
void FetchMethods(std::vector<Unity::il2cppMethodInfo*>* m_pVector, void* m_pMethodIterator = nullptr)
{
Class::FetchMethods(m_Object.m_pClass, m_pVector, m_pMethodIterator);
}
void* GetMethodPointer(const char* m_pMethodName, int m_iArgs = -1)
{
return Class::Utils::GetMethodPointer(m_Object.m_pClass, m_pMethodName, m_iArgs);
}
m_eClassPropType GetPropType(const char* m_pPropType)
{
Unity::il2cppFieldInfo* pField = reinterpret_cast<Unity::il2cppFieldInfo*(IL2CPP_CALLING_CONVENTION)(void*, const char*)>(Data.Functions.m_pClassGetFieldFromName)(m_Object.m_pClass, m_pPropType);
if (pField)
return m_eClassPropType::Field;
Unity::il2cppPropertyInfo* pProperty = reinterpret_cast<Unity::il2cppPropertyInfo*(IL2CPP_CALLING_CONVENTION)(void*, const char*)>(Data.Functions.m_pClassGetPropertyFromName)(m_Object.m_pClass, m_pPropType);
if (pProperty)
return m_eClassPropType::Property;
Unity::il2cppMethodInfo* pMethod = reinterpret_cast<Unity::il2cppMethodInfo*(IL2CPP_CALLING_CONVENTION)(void*, const char*, int)>(Data.Functions.m_pClassGetMethodFromName)(m_Object.m_pClass, m_pPropType, -1);
if (pMethod)
return m_eClassPropType::Method;
return m_eClassPropType::Unknown;
}
// Call Method
template<typename TReturn, typename... TArgs>
TReturn CallMethod(void* m_pMethod, TArgs... tArgs) { return reinterpret_cast<TReturn(UNITY_CALLING_CONVENTION)(void*, TArgs...)>(m_pMethod)(this, tArgs...); }
template<typename TReturn, typename... TArgs>
TReturn CallMethod(const char* m_pMethodName, TArgs... tArgs) { return CallMethod<TReturn>(GetMethodPointer(m_pMethodName), tArgs...); }
template<typename TReturn, typename... TArgs>
TReturn CallMethodSafe(void* m_pMethod, TArgs... tArgs)
{
if (!m_pMethod)
{
#ifdef _DEBUG
__debugbreak(); // remove it when you wanna step through your code and be like why the fuck it doesn't do anything.
#endif
TReturn m_tDefault = {}; // void goes like illegal use of type. (use void* and fuck them)
return m_tDefault;
}
return CallMethod<TReturn>(m_pMethod, tArgs...);
}
template<typename TReturn, typename... TArgs>
TReturn CallMethodSafe(const char* m_pMethodName, TArgs... tArgs) { return CallMethodSafe<TReturn>(GetMethodPointer(m_pMethodName), tArgs...); }
// Properties/Fields
template<typename T>
T GetPropertyValue(const char* m_pPropertyName)
{
Unity::il2cppPropertyInfo* pProperty = reinterpret_cast<Unity::il2cppPropertyInfo*(IL2CPP_CALLING_CONVENTION)(void*, const char*)>(Data.Functions.m_pClassGetPropertyFromName)(m_Object.m_pClass, m_pPropertyName);
if (pProperty && pProperty->m_pGet)
return reinterpret_cast<T(UNITY_CALLING_CONVENTION)(void*)>(pProperty->m_pGet->m_pMethodPointer)(this);
T tDefault = {};
return tDefault;
}
template<typename T>
void SetPropertyValue(const char* m_pPropertyName, T m_tValue)
{
Unity::il2cppPropertyInfo* pProperty = reinterpret_cast<Unity::il2cppPropertyInfo*(IL2CPP_CALLING_CONVENTION)(void*, const char*)>(Data.Functions.m_pClassGetPropertyFromName)(m_Object.m_pClass, m_pPropertyName);
if (pProperty && pProperty->m_pSet)
return reinterpret_cast<void(UNITY_CALLING_CONVENTION)(void*, T)>(pProperty->m_pSet->m_pMethodPointer)(this, m_tValue);
}
template<typename T>
__inline T GetMemberValue(int m_iOffset)
{
return *reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(this) + m_iOffset);
}
template<typename T>
__inline void SetMemberValue(int m_iOffset, T m_tValue)
{
*reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(this) + m_iOffset) = m_tValue;
}
template<typename T>
__inline T GetMemberValue(Unity::il2cppFieldInfo* m_pField)
{
if (!m_pField || 0 > m_pField->m_iOffset)
{
T m_tDefault = {};
return m_tDefault;
}
return GetMemberValue<T>(m_pField->m_iOffset);
}
template<typename T>
__inline void SetMemberValue(Unity::il2cppFieldInfo* m_pField, T m_tValue)
{
if (!m_pField || 0 > m_pField->m_iOffset)
return;
SetMemberValue<T>(m_pField->m_iOffset, m_tValue);
}
template<typename T>
T GetMemberValue(const char* m_pMemberName)
{
Unity::il2cppFieldInfo* pField = reinterpret_cast<Unity::il2cppFieldInfo*(IL2CPP_CALLING_CONVENTION)(void*, const char*)>(Data.Functions.m_pClassGetFieldFromName)(m_Object.m_pClass, m_pMemberName);
if (pField)
{
if (pField->m_iOffset >= 0) return *reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(this) + pField->m_iOffset);
}
else
return GetPropertyValue<T>(m_pMemberName);
T tDefault = {};
return tDefault;
}
template<typename T>
void SetMemberValue(const char* m_pMemberName, T m_tValue)
{
Unity::il2cppFieldInfo* pField = reinterpret_cast<Unity::il2cppFieldInfo*(IL2CPP_CALLING_CONVENTION)(void*, const char*)>(Data.Functions.m_pClassGetFieldFromName)(m_Object.m_pClass, m_pMemberName);
if (pField)
{
if (pField->m_iOffset >= 0) *reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(this) + pField->m_iOffset) = m_tValue;
return;
}
SetPropertyValue<T>(m_pMemberName, m_tValue);
}
template<typename T>
__inline T GetObscuredViaOffset(int m_iOffset)
{
if (m_iOffset >= 0)
{
switch (sizeof(T))
{
case sizeof(double):
{
long long m_lKey = *reinterpret_cast<long long*>(reinterpret_cast<uintptr_t>(this) + m_iOffset);
long long m_lValue = *reinterpret_cast<long long*>(reinterpret_cast<uintptr_t>(this) + m_iOffset + sizeof(m_lKey));
m_lValue ^= m_lKey;
return *reinterpret_cast<T*>(&m_lValue);
}
break;
case sizeof(int):
{
int m_iKey = *reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(this) + m_iOffset);
int m_iValue = *reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(this) + m_iOffset + sizeof(m_iKey));
m_iValue ^= m_iKey;
return *reinterpret_cast<T*>(&m_iValue);
}
break;
case sizeof(bool):
{
unsigned char m_uKey = *reinterpret_cast<unsigned char*>(reinterpret_cast<uintptr_t>(this) + m_iOffset);
int m_iValue = *reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(this) + m_iOffset + sizeof(m_uKey));
m_iValue ^= m_uKey;
return *reinterpret_cast<T*>(&m_iValue);
}
break;
}
}
T m_tDefault = { 0 };
return m_tDefault;
}
template<typename T>
T GetObscuredValue(const char* m_pMemberName)
{
Unity::il2cppFieldInfo* m_pField = reinterpret_cast<Unity::il2cppFieldInfo*(IL2CPP_CALLING_CONVENTION)(void*, const char*)>(Data.Functions.m_pClassGetFieldFromName)(m_Object.m_pClass, m_pMemberName);
return GetObscuredViaOffset<T>(m_pField ? m_pField->m_iOffset : -1);
}
template<typename T>
__inline void SetObscuredViaOffset(int m_iOffset, T m_tValue)
{
if (0 > m_iOffset)
return;
switch (sizeof(T))
{
case sizeof(double):
{
long long m_lKey = *reinterpret_cast<long long*>(reinterpret_cast<uintptr_t>(this) + m_iOffset);
long long* m_pValue = reinterpret_cast<long long*>(reinterpret_cast<uintptr_t>(this) + m_iOffset + sizeof(m_lKey));
*m_pValue = *reinterpret_cast<long long*>(&m_tValue) ^ m_lKey;
}
break;
case sizeof(int):
{
int m_iKey = *reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(this) + m_iOffset);
int* m_pValue = reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(this) + m_iOffset + sizeof(m_iKey));
*m_pValue = *reinterpret_cast<int*>(&m_tValue) ^ m_iKey;
}
break;
case sizeof(bool):
{
unsigned char m_uKey = *reinterpret_cast<unsigned char*>(reinterpret_cast<uintptr_t>(this) + m_iOffset);
int* m_pValue = reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(this) + m_iOffset + sizeof(m_uKey));
*m_pValue = *reinterpret_cast<int*>(&m_tValue) ^ m_uKey;
}
break;
}
}
template<typename T>
void SetObscuredValue(const char* m_pMemberName, T m_tValue)
{
Unity::il2cppFieldInfo* m_pField = reinterpret_cast<Unity::il2cppFieldInfo*(IL2CPP_CALLING_CONVENTION)(void*, const char*)>(Data.Functions.m_pClassGetFieldFromName)(m_Object.m_pClass, m_pMemberName);
if (!m_pField)
return;
SetObscuredViaOffset<T>(m_pField->m_iOffset, m_tValue);
}
};
}

View File

@@ -0,0 +1,17 @@
#pragma once
namespace IL2CPP
{
namespace Domain
{
static void* Get()
{
return reinterpret_cast<void*(IL2CPP_CALLING_CONVENTION)()>(Data.Functions.m_pDomainGet)();
}
static Unity::il2cppAssembly** GetAssemblies(size_t* m_pSize)
{
return reinterpret_cast<Unity::il2cppAssembly**(IL2CPP_CALLING_CONVENTION)(void*, size_t*)>(Data.Functions.m_pDomainGetAssemblies)(Get(), m_pSize);
}
}
}

View File

@@ -0,0 +1,10 @@
#pragma once
namespace IL2CPP
{
// Without this function, you're pretty much fucked up.
static void* ResolveCall(const char* m_pName)
{
return reinterpret_cast<void*(IL2CPP_CALLING_CONVENTION)(const char*)>(Data.Functions.m_pResolveFunction)(m_pName);
}
}

View File

@@ -0,0 +1,28 @@
#include "../Includes.hpp"
namespace IL2CPP
{
namespace String
{
Unity::System_String* New(const char* m_pString)
{
return reinterpret_cast<Unity::System_String*(IL2CPP_CALLING_CONVENTION)(const char*)>(Data.Functions.m_pStringNew)(m_pString);
}
Unity::System_String* New(std::string m_sString) { return New(&m_sString[0]); }
namespace NoGC
{
Unity::System_String* New(const char* m_pString)
{
Unity::System_String* m_pNew = new Unity::System_String;
m_pNew->m_pClass = IL2CPP::Class::Find("System.String");
m_pNew->m_iLength = swprintf_s(m_pNew->m_wString, (sizeof(Unity::System_String::m_wString) / 4), L"%hs", m_pString);
return m_pNew;
}
Unity::System_String* New(std::string m_sString) { return New(&m_sString[0]); }
}
}
}

View File

@@ -0,0 +1,19 @@
#pragma once
namespace IL2CPP
{
namespace String
{
Unity::System_String* New(const char* m_pString);
Unity::System_String* New(std::string m_sString);
// Make sure to delete it after you done using it.
namespace NoGC
{
Unity::System_String* New(const char* m_pString);
Unity::System_String* New(std::string m_sString);
}
}
}

View File

@@ -0,0 +1,21 @@
#include "../Includes.hpp"
namespace IL2CPP
{
DWORD __stdcall ThreadHandler(void* pReserved)
{
void* m_pIL2CPPThread = Thread::Attach(Domain::Get());
CThread* m_pThread = reinterpret_cast<CThread*>(pReserved);
void* m_pThreadStart = m_pThread->m_pThreadOnStart;
void* m_pThreadEnd = m_pThread->m_pThreadOnEnd;
delete m_pThread;
reinterpret_cast<void(*)()>(m_pThreadStart)();
if (m_pThreadEnd)
reinterpret_cast<void(*)()>(m_pThreadEnd)();
Thread::Detach(m_pIL2CPPThread);
return 0x0;
}
}

View File

@@ -0,0 +1,47 @@
#pragma once
namespace IL2CPP
{
DWORD __stdcall ThreadHandler(void* pReserved);
class CThread
{
public:
void* m_pThreadOnStart = nullptr;
void* m_pThreadOnEnd = nullptr;
CThread() { /* Why would you even do this? */ }
CThread(void* m_pOnStart, void* m_pOnEnd)
{
m_pThreadOnStart = m_pOnStart;
m_pThreadOnEnd = m_pOnEnd;
if (!m_pThreadOnStart)
{
IL2CPP_ASSERT("IL2CPP::CThread - m_pThreadOnStart is nullptr");
return;
}
CreateThread(0, 0, ThreadHandler, this, 0, 0);
}
};
namespace Thread
{
static void Create(void* m_pOnStart, void* m_pOnEnd = nullptr)
{
CThread* pThread = new CThread(m_pOnStart, m_pOnEnd);
IL2CPP_ASSERT(pThread && "IL2CPP::Thread::Create - Failed!");
}
static void* Attach(void* m_pDomain)
{
return reinterpret_cast<void*(IL2CPP_CALLING_CONVENTION)(void*)>(IL2CPP::Data.Functions.m_pThreadAttach)(m_pDomain);
}
static void Detach(void* m_pThread)
{
reinterpret_cast<void(IL2CPP_CALLING_CONVENTION)(void*)>(IL2CPP::Data.Functions.m_pThreadDetach)(m_pThread);
}
}
}

View File

@@ -0,0 +1,42 @@
#pragma once
// Disable Asserts
// #define IL2CPP_ASSERT(x) ((void)(x))
#include "Defines.hpp"
#define _USE_MATH_DEFINES
#include <math.h>
#include <assert.h>
#include <unordered_map>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <string>
// Unity
#include "Unity/Includes.hpp"
// IL2CPP API
#include "Data.hpp" // Pointers, Variables, etc...
#include "Cache.hpp"
// IL2CPP
#include "Functions/Callback.hpp"
#include "Functions/Class.hpp"
#include "Functions/Domain.hpp"
#include "Functions/ResolveCall.hpp"
#include "Functions/String.hpp"
#include "Functions/Thread.hpp"
// Unity API - Include here so we have access to some cute IL2CPP Features
#include "Unity/API/_TEMPLATE_API.hpp"
#include "Unity/API/Object.hpp"
#include "Unity/API/Component.hpp"
#include "Unity/API/GameObject.hpp"
#include "Unity/API/Camera.hpp"
#include "Unity/API/LayerMask.hpp"
#include "Unity/API/Rigidbody.hpp"
#include "Unity/API/Transform.hpp"
// Utils
#include "Utils/Helper.hpp"
#include "Utils/Joaat.hpp"
#include "Utils/VFunc.hpp"

View File

@@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <https://unlicense.org>

View File

@@ -0,0 +1,36 @@
## IL2CPP Resolver
A run-time API resolver for IL2CPP Unity.
[![Donate](https://img.shields.io/badge/Donate-PayPal-red.svg)](https://www.paypal.com/donate/?hosted_button_id=F86FFE644E55E)
### Quick Example
```cpp
#include "Main.hpp"
void SomeFunction()
{
IL2CPP::Initialize(); // This needs to be called once!
Unity::CGameObject* pLocal = Unity::GameObject::Find("LocalPlayer");
Unity::CComponent* pLocalData = pLocal->GetComponent("PlayerData");
pLocalData->SetMemberValue<bool>("CanFly", true);
}
```
### Registering OnUpdate Callback
```cpp
void OurUpdateFunction()
{
// Your special code...
}
void OnLoad()
{
IL2CPP::Initialize();
IL2CPP::Callback::Initialize();
IL2CPP::Callback::OnUpdate::Add(OurUpdateFunction);
}
```
More: https://sneakyevil.gitbook.io/il2cpp-resolver/

View File

@@ -0,0 +1,32 @@
#include "../../Includes.hpp"
namespace Unity
{
SCameraFunctions CameraFunctions;
namespace Camera
{
void Initialize()
{
IL2CPP::SystemTypeCache::Initializer::Add(UNITY_CAMERA_CLASS);
CameraFunctions.m_pGetCurrent = IL2CPP::ResolveCall(UNITY_CAMERA_GETCURRENT);
CameraFunctions.m_pGetMain = IL2CPP::ResolveCall(UNITY_CAMERA_GETMAIN);
CameraFunctions.m_pGetDepth = IL2CPP::ResolveCall(UNITY_CAMERA_GETDEPTH);
CameraFunctions.m_pSetDepth = IL2CPP::ResolveCall(UNITY_CAMERA_SETDEPTH);
CameraFunctions.m_pGetFieldOfView = IL2CPP::ResolveCall(UNITY_CAMERA_GETFIELDOFVIEW);
CameraFunctions.m_pSetFieldOfView = IL2CPP::ResolveCall(UNITY_CAMERA_SETFIELDOFVIEW);
CameraFunctions.m_pWorldToScreen = IL2CPP::ResolveCall(UNITY_CAMERA_WORLDTOSCREEN);
}
CCamera* GetCurrent()
{
return reinterpret_cast<CCamera*(UNITY_CALLING_CONVENTION)()>(CameraFunctions.m_pGetCurrent)();
}
CCamera* GetMain()
{
return reinterpret_cast<CCamera*(UNITY_CALLING_CONVENTION)()>(CameraFunctions.m_pGetMain)();
}
}
}

View File

@@ -0,0 +1,70 @@
#pragma once
namespace Unity
{
struct SCameraFunctions
{
void* m_pGetCurrent = nullptr;
void* m_pGetMain = nullptr;
void* m_pGetDepth = nullptr;
void* m_pSetDepth = nullptr;
void* m_pGetFieldOfView = nullptr;
void* m_pSetFieldOfView = nullptr;
void* m_pWorldToScreen = nullptr;
};
extern SCameraFunctions CameraFunctions;
class CCamera : public CGameObject
{
public:
float GetDepth()
{
return reinterpret_cast<float(UNITY_CALLING_CONVENTION)(void*)>(CameraFunctions.m_pGetDepth)(this);
}
void SetDepth(float m_fValue)
{
reinterpret_cast<void(UNITY_CALLING_CONVENTION)(void*, float)>(CameraFunctions.m_pSetDepth)(this, m_fValue);
}
float GetFieldOfView()
{
return reinterpret_cast<float(UNITY_CALLING_CONVENTION)(void*)>(CameraFunctions.m_pGetFieldOfView)(this);
}
void SetFieldOfView(float m_fValue)
{
reinterpret_cast<void(UNITY_CALLING_CONVENTION)(void*, float)>(CameraFunctions.m_pSetFieldOfView)(this, m_fValue);
}
void WorldToScreen(Vector3& m_vWorld, Vector3& m_vScreen, int m_iEye = 2)
{
reinterpret_cast<void(UNITY_CALLING_CONVENTION)(void*, Vector3&, int, Vector3&)>(CameraFunctions.m_pWorldToScreen)(this, m_vWorld, m_iEye, m_vScreen);
}
};
namespace Camera
{
void Initialize();
CCamera* GetCurrent();
CCamera* GetMain();
}
enum m_eCameraType : int
{
m_eCameraType_Game = 1,
m_eCameraType_SceneView = 2,
m_eCameraType_Preview = 4,
m_eCameraType_VR = 8,
m_eCameraType_Reflection = 16,
};
enum m_eCameraEye : int
{
m_eCameraEye_Left = 0,
m_eCameraEye_Right = 1,
m_eCameraEye_Center = 2,
};
}

View File

@@ -0,0 +1,17 @@
#include "../../Includes.hpp"
namespace Unity
{
SComponentFunctions ComponentFunctions;
namespace Component
{
void Initialize()
{
IL2CPP::SystemTypeCache::Initializer::Add(UNITY_COMPONENT_CLASS);
ComponentFunctions.m_pGetGameObject = IL2CPP::ResolveCall(UNITY_COMPONENT_GETGAMEOBJECT);
ComponentFunctions.m_pGetTransform = IL2CPP::ResolveCall(UNITY_COMPONENT_GETTRANSFORM);
}
}
}

View File

@@ -0,0 +1,30 @@
#pragma once
namespace Unity
{
struct SComponentFunctions
{
void* m_pGetGameObject = nullptr;
void* m_pGetTransform = nullptr;
};
extern SComponentFunctions ComponentFunctions;
class CComponent : public CObject
{
public:
CGameObject* GetGameObject()
{
return reinterpret_cast<CGameObject*(UNITY_CALLING_CONVENTION)(void*)>(ComponentFunctions.m_pGetGameObject)(this);
}
CTransform* GetTransform()
{
return reinterpret_cast<CTransform*(UNITY_CALLING_CONVENTION)(void*)>(ComponentFunctions.m_pGetTransform)(this);
}
};
namespace Component
{
void Initialize();
}
}

View File

@@ -0,0 +1,41 @@
#include "../../Includes.hpp"
namespace Unity
{
SGameObjectFunctions GameObjectFunctions;
namespace GameObject
{
void Initialize()
{
IL2CPP::SystemTypeCache::Initializer::Add(UNITY_GAMEOBJECT_CLASS);
GameObjectFunctions.m_pAddComponent = IL2CPP::ResolveCall(UNITY_GAMEOBJECT_ADDCOMPONENT);
GameObjectFunctions.m_pCreatePrimitive = IL2CPP::ResolveCall(UNITY_GAMEOBJECT_CREATEPRIMITIVE);
GameObjectFunctions.m_pFind = IL2CPP::ResolveCall(UNITY_GAMEOBJECT_FIND);
GameObjectFunctions.m_pFindGameObjectsWithTag = IL2CPP::ResolveCall(UNITY_GAMEOBJECT_FINDGAMEOBJECTWITHTAG);
GameObjectFunctions.m_pGetComponent = IL2CPP::ResolveCall(UNITY_GAMEOBJECT_GETCOMPONENT);
GameObjectFunctions.m_pGetComponents = IL2CPP::ResolveCall(UNITY_GAMEOBJECT_GETCOMPONENTS);
GameObjectFunctions.m_pGetActive = IL2CPP::ResolveCall(UNITY_GAMEOBJECT_GETACTIVE);
GameObjectFunctions.m_pGetLayer = IL2CPP::ResolveCall(UNITY_GAMEOBJECT_GETLAYER);
GameObjectFunctions.m_pGetTransform = IL2CPP::ResolveCall(UNITY_GAMEOBJECT_GETTRANSFORM);
GameObjectFunctions.m_pSetActive = IL2CPP::ResolveCall(UNITY_GAMEOBJECT_SETACTIVE);
GameObjectFunctions.m_pSetLayer = IL2CPP::ResolveCall(UNITY_GAMEOBJECT_SETLAYER);
}
CGameObject* CreatePrimitive(m_ePrimitiveType m_eType)
{
return reinterpret_cast<CGameObject*(UNITY_CALLING_CONVENTION)(m_ePrimitiveType)>(GameObjectFunctions.m_pCreatePrimitive)(m_eType);
}
CGameObject* Find(const char* m_pName)
{
return reinterpret_cast<CGameObject*(UNITY_CALLING_CONVENTION)(System_String*)>(GameObjectFunctions.m_pFind)(IL2CPP::String::New(m_pName));
}
il2cppArray<CGameObject*>* FindWithTag(const char* m_pTag)
{
return reinterpret_cast<il2cppArray<CGameObject*>*(UNITY_CALLING_CONVENTION)(void*)>(GameObjectFunctions.m_pFindGameObjectsWithTag)(IL2CPP::String::New(m_pTag));
}
}
}

View File

@@ -0,0 +1,122 @@
#pragma once
namespace Unity
{
struct SGameObjectFunctions
{
void* m_pAddComponent = nullptr;
void* m_pCreatePrimitive = nullptr;
void* m_pFind = nullptr;
void* m_pFindGameObjectsWithTag = nullptr;
void* m_pGetComponent = nullptr;
void* m_pGetComponents = nullptr;
void* m_pGetActive = nullptr;
void* m_pGetLayer = nullptr;
void* m_pGetTransform = nullptr;
void* m_pSetActive = nullptr;
void* m_pSetLayer = nullptr;
};
extern SGameObjectFunctions GameObjectFunctions;
class CGameObject : public CObject
{
public:
void AddComponent(il2cppObject* m_pSystemType)
{
reinterpret_cast<void(UNITY_CALLING_CONVENTION)(void*, void*)>(GameObjectFunctions.m_pAddComponent)(this, m_pSystemType);
}
CComponent* GetComponent(const char* m_pName)
{
return reinterpret_cast<CComponent*(UNITY_CALLING_CONVENTION)(void*, System_String*)>(GameObjectFunctions.m_pGetComponent)(this, IL2CPP::String::New(m_pName));
}
il2cppArray<CComponent*>* GetComponents(il2cppObject* m_pSystemType)
{
/*
0 - Object
1 - Type
2 - Use search type as array return type
3 - Recursive
4 - Include inactive
5 - Reverse
6 - Result list
*/
return reinterpret_cast<Unity::il2cppArray<CComponent*>*(UNITY_CALLING_CONVENTION)(void*, void*, bool, bool, bool, bool, void*)>(GameObjectFunctions.m_pGetComponents)(this, m_pSystemType, false, false, true, false, nullptr);
}
il2cppArray<CComponent*>* GetComponents(const char* m_pSystemTypeName)
{
il2cppClass* m_pClass = IL2CPP::Class::Find(m_pSystemTypeName);
if (!m_pClass) return nullptr;
return GetComponents(IL2CPP::Class::GetSystemType(m_pClass));
}
CComponent* GetComponentByIndex(il2cppObject* m_pSystemType, unsigned int m_uIndex = 0U)
{
il2cppArray<CComponent*>* m_pComponents = GetComponents(m_pSystemType);
if (!m_pComponents || m_uIndex >= m_pComponents->m_uMaxLength) return nullptr;
return m_pComponents->operator[](m_uIndex);
}
CComponent* GetComponentByIndex(const char* m_pSystemTypeName, unsigned int m_uIndex = 0U)
{
il2cppClass* m_pClass = IL2CPP::Class::Find(m_pSystemTypeName);
if (!m_pClass) return nullptr;
return GetComponentByIndex(IL2CPP::Class::GetSystemType(m_pClass), m_uIndex);
}
CTransform* GetTransform()
{
return reinterpret_cast<CTransform*(UNITY_CALLING_CONVENTION)(void*)>(GameObjectFunctions.m_pGetTransform)(this);
}
bool GetActive()
{
return reinterpret_cast<bool(UNITY_CALLING_CONVENTION)(void*)>(GameObjectFunctions.m_pGetActive)(this);
}
unsigned int GetLayer()
{
return reinterpret_cast<unsigned int(UNITY_CALLING_CONVENTION)(void*)>(GameObjectFunctions.m_pGetLayer)(this);
}
/*
* (WARNING) when you use GameObject::Find and you set the object to unactive, you won't find it anymore with that slow function.
*/
void SetActive(bool m_bActive)
{
reinterpret_cast<void(UNITY_CALLING_CONVENTION)(void*, bool)>(GameObjectFunctions.m_pSetActive)(this, m_bActive);
}
void SetLayer(unsigned int m_uLayer)
{
reinterpret_cast<void(UNITY_CALLING_CONVENTION)(void*, unsigned int)>(GameObjectFunctions.m_pSetLayer)(this, m_uLayer);
}
};
namespace GameObject
{
enum class m_ePrimitiveType : int
{
Default = 0,
Sphere = 0,
Capsule,
Cylinder,
Cube,
Plane,
Quad,
};
void Initialize();
CGameObject* CreatePrimitive(m_ePrimitiveType m_eType);
CGameObject* Find(const char* m_pName);
il2cppArray<CGameObject*>* FindWithTag(const char* m_pTag);
}
}

View File

@@ -0,0 +1,17 @@
#include "../../Includes.hpp"
namespace Unity
{
SLayerMaskFunctions LayerMaskFunctions;
namespace LayerMask
{
void Initialize()
{
IL2CPP::SystemTypeCache::Initializer::Add(UNITY_LAYERMASK_CLASS);
LayerMaskFunctions.m_pLayerToName = IL2CPP::ResolveCall(UNITY_LAYERMASK_LAYERTONAME);
LayerMaskFunctions.m_pNameToLayer = IL2CPP::ResolveCall(UNITY_LAYERMASK_NAMETOLAYER);
}
}
}

View File

@@ -0,0 +1,26 @@
#pragma once
namespace Unity
{
struct SLayerMaskFunctions
{
void* m_pLayerToName = nullptr;
void* m_pNameToLayer = nullptr;
};
extern SLayerMaskFunctions LayerMaskFunctions;
namespace LayerMask
{
void Initialize();
static System_String* LayerToName(unsigned int m_uLayer)
{
return reinterpret_cast<System_String*(UNITY_CALLING_CONVENTION)(unsigned int)>(LayerMaskFunctions.m_pLayerToName)(m_uLayer);
}
static unsigned int NameToLayer(const char* m_pName)
{
return reinterpret_cast<unsigned int(UNITY_CALLING_CONVENTION)(void*)>(LayerMaskFunctions.m_pNameToLayer)(IL2CPP::String::New(m_pName));
}
}
}

View File

@@ -0,0 +1,18 @@
#include "../../Includes.hpp"
namespace Unity
{
SObjectFunctions ObjectFunctions;
namespace Object
{
void Initialize()
{
IL2CPP::SystemTypeCache::Initializer::Add(UNITY_OBJECT_CLASS);
ObjectFunctions.m_pDestroy = IL2CPP::ResolveCall(UNITY_OBJECT_DESTROY);
ObjectFunctions.m_pFindObjectsOfType = IL2CPP::ResolveCall(UNITY_OBJECT_FINDOBJECTSOFTYPE);
ObjectFunctions.m_pGetName = IL2CPP::ResolveCall(UNITY_OBJECT_GETNAME);
}
}
}

View File

@@ -0,0 +1,64 @@
#pragma once
namespace Unity
{
struct SObjectFunctions
{
void* m_pDestroy = nullptr;
void* m_pFindObjectsOfType = nullptr;
void* m_pGetName = nullptr;
};
extern SObjectFunctions ObjectFunctions;
class CObject : public IL2CPP::CClass
{
public:
void Destroy(float fTimeDelay = 0.f)
{
reinterpret_cast<void(UNITY_CALLING_CONVENTION)(void*, float)>(ObjectFunctions.m_pDestroy)(this, fTimeDelay);
}
System_String* GetName()
{
return reinterpret_cast<System_String*(UNITY_CALLING_CONVENTION)(void*)>(ObjectFunctions.m_pGetName)(this);
}
};
namespace Object
{
void Initialize();
template<typename T>
static il2cppArray<T*>* FindObjectsOfType(il2cppObject* m_pSystemType)
{
return reinterpret_cast<Unity::il2cppArray<T*>*(UNITY_CALLING_CONVENTION)(void*)>(ObjectFunctions.m_pFindObjectsOfType)(m_pSystemType);
}
template<typename T>
static il2cppArray<T*>* FindObjectsOfType(const char* m_pSystemTypeName)
{
il2cppClass* m_pClass = IL2CPP::Class::Find(m_pSystemTypeName);
if (!m_pClass) return nullptr;
return FindObjectsOfType<T>(IL2CPP::Class::GetSystemType(m_pClass));
}
template<typename T>
static T* FindObjectOfType(il2cppObject* m_pSystemType)
{
il2cppArray<T*>* m_pArray = FindObjectsOfType<T>(m_pSystemType);
if (!m_pArray || m_pArray->m_uMaxLength == 0U) return nullptr;
return m_pArray->m_pValues[0];
}
template<typename T>
static T* FindObjectOfType(const char* m_pSystemTypeName)
{
il2cppClass* m_pClass = IL2CPP::Class::Find(m_pSystemTypeName);
if (!m_pClass) return nullptr;
return FindObjectOfType<T>(IL2CPP::Class::GetSystemType(m_pClass));
}
}
}

View File

@@ -0,0 +1,20 @@
#include "../../Includes.hpp"
namespace Unity
{
SRigidbodyFunctions RigidbodyFunctions;
namespace RigidBody
{
void Initialize()
{
IL2CPP::SystemTypeCache::Initializer::Add(UNITY_RIGIDBODY_CLASS);
RigidbodyFunctions.m_pGetDetectCollisions = IL2CPP::ResolveCall(UNITY_RIGIDBODY_GETDETECTCOLLISIONS);
RigidbodyFunctions.m_pGetVelocity = IL2CPP::ResolveCall(UNITY_RIGIDBODY_GETVELOCITY);
RigidbodyFunctions.m_pSetDetectCollisions = IL2CPP::ResolveCall(UNITY_RIGIDBODY_SETDETECTCOLLISIONS);
RigidbodyFunctions.m_pSetVelocity = IL2CPP::ResolveCall(UNITY_RIGIDBODY_SETVELOCITY);
}
}
}

View File

@@ -0,0 +1,44 @@
#pragma once
namespace Unity
{
struct SRigidbodyFunctions
{
void* m_pGetDetectCollisions = nullptr;
void* m_pGetVelocity = nullptr;
void* m_pSetDetectCollisions = nullptr;
void* m_pSetVelocity = nullptr;
};
extern SRigidbodyFunctions RigidbodyFunctions;
class CRigidbody : public IL2CPP::CClass
{
public:
bool GetDetectCollisions()
{
return reinterpret_cast<bool(UNITY_CALLING_CONVENTION)(void*)>(RigidbodyFunctions.m_pGetDetectCollisions)(this);
}
void SetDetectCollisions(bool m_bDetect)
{
reinterpret_cast<void(UNITY_CALLING_CONVENTION)(void*, bool)>(RigidbodyFunctions.m_pSetDetectCollisions)(this, m_bDetect);
}
Vector3 GetVelocity()
{
Vector3 vRet;
reinterpret_cast<void(UNITY_CALLING_CONVENTION)(void*, Vector3&)>(RigidbodyFunctions.m_pGetVelocity)(this, vRet);
return vRet;
}
void SetVelocity(Vector3 m_vVector)
{
reinterpret_cast<void(UNITY_CALLING_CONVENTION)(void*, Vector3)>(RigidbodyFunctions.m_pSetVelocity)(this, m_vVector);
}
};
namespace RigidBody
{
void Initialize();
}
}

View File

@@ -0,0 +1,27 @@
#include "../../Includes.hpp"
namespace Unity
{
STransformFunctions TransformFunctions;
namespace Transform
{
void Initialize()
{
IL2CPP::SystemTypeCache::Initializer::Add(UNITY_TRANSFORM_CLASS);
TransformFunctions.m_pGetParent = IL2CPP::ResolveCall(UNITY_TRANSFORM_GETPARENT);
TransformFunctions.m_pGetRoot = IL2CPP::ResolveCall(UNITY_TRANSFORM_GETROOT);
TransformFunctions.m_pGetChild = IL2CPP::ResolveCall(UNITY_TRANSFORM_GETCHILD);
TransformFunctions.m_pGetChildCount = IL2CPP::ResolveCall(UNITY_TRANSFORM_GETCHILDCOUNT);
TransformFunctions.m_pGetPosition = IL2CPP::ResolveCall(UNITY_TRANSFORM_GETPOSITION);
TransformFunctions.m_pGetRotation = IL2CPP::ResolveCall(UNITY_TRANSFORM_GETROTATION);
TransformFunctions.m_pGetLocalPosition = IL2CPP::ResolveCall(UNITY_TRANSFORM_GETLOCALPOSITION);
TransformFunctions.m_pGetLocalScale = IL2CPP::ResolveCall(UNITY_TRANSFORM_GETLOCALSCALE);
TransformFunctions.m_pSetPosition = IL2CPP::ResolveCall(UNITY_TRANSFORM_SETPOSITION);
TransformFunctions.m_pSetRotation = IL2CPP::ResolveCall(UNITY_TRANSFORM_SETROTATION);
TransformFunctions.m_pSetLocalPosition = IL2CPP::ResolveCall(UNITY_TRANSFORM_SETLOCALPOSITION);
TransformFunctions.m_pSetLocalScale = IL2CPP::ResolveCall(UNITY_TRANSFORM_SETLOCALSCALE);
}
}
}

View File

@@ -0,0 +1,98 @@
#pragma once
namespace Unity
{
struct STransformFunctions
{
void* m_pGetParent = nullptr;
void* m_pGetRoot = nullptr;
void* m_pGetChild = nullptr;
void* m_pGetChildCount = nullptr;
void* m_pGetPosition = nullptr;
void* m_pGetRotation = nullptr;
void* m_pGetLocalPosition = nullptr;
void* m_pGetLocalScale = nullptr;
void* m_pSetPosition = nullptr;
void* m_pSetRotation = nullptr;
void* m_pSetLocalPosition = nullptr;
void* m_pSetLocalScale = nullptr;
};
extern STransformFunctions TransformFunctions;
class CTransform : public IL2CPP::CClass
{
public:
CTransform* GetParent()
{
return reinterpret_cast<CTransform*(UNITY_CALLING_CONVENTION)(void*)>(TransformFunctions.m_pGetParent)(this);
}
CTransform* GetRoot()
{
return reinterpret_cast<CTransform*(UNITY_CALLING_CONVENTION)(void*)>(TransformFunctions.m_pGetRoot)(this);
}
CTransform* GetChild(int m_iIndex)
{
return reinterpret_cast<CTransform*(UNITY_CALLING_CONVENTION)(void*, int)>(TransformFunctions.m_pGetChild)(this, m_iIndex);
}
int GetChildCount()
{
return reinterpret_cast<int(UNITY_CALLING_CONVENTION)(void*)>(TransformFunctions.m_pGetChildCount)(this);
}
Vector3 GetPosition()
{
Vector3 vRet;
reinterpret_cast<void(UNITY_CALLING_CONVENTION)(void*, Vector3&)>(TransformFunctions.m_pGetPosition)(this, vRet);
return vRet;
}
Quaternion GetRotation()
{
Quaternion m_qRet;
reinterpret_cast<void(UNITY_CALLING_CONVENTION)(void*, Quaternion&)>(TransformFunctions.m_pGetRotation)(this, m_qRet);
return m_qRet;
}
Vector3 GetLocalPosition()
{
Vector3 vRet;
reinterpret_cast<void(UNITY_CALLING_CONVENTION)(void*, Vector3&)>(TransformFunctions.m_pGetLocalPosition)(this, vRet);
return vRet;
}
Vector3 GetLocalScale()
{
Vector3 vRet;
reinterpret_cast<void(UNITY_CALLING_CONVENTION)(void*, Vector3&)>(TransformFunctions.m_pGetLocalScale)(this, vRet);
return vRet;
}
void SetPosition(Vector3 m_vVector)
{
reinterpret_cast<void(UNITY_CALLING_CONVENTION)(void*, Vector3)>(TransformFunctions.m_pSetPosition)(this, m_vVector);
}
void SetRotation(Quaternion m_qQuat)
{
reinterpret_cast<void(UNITY_CALLING_CONVENTION)(void*, Quaternion)>(TransformFunctions.m_pSetRotation)(this, m_qQuat);
}
void SetLocalPosition(Vector3 m_vVector)
{
reinterpret_cast<void(UNITY_CALLING_CONVENTION)(void*, Vector3)>(TransformFunctions.m_pSetLocalPosition)(this, m_vVector);
}
void SetLocalScale(Vector3 m_vVector)
{
reinterpret_cast<void(UNITY_CALLING_CONVENTION)(void*, Vector3)>(TransformFunctions.m_pSetLocalScale)(this, m_vVector);
}
};
namespace Transform
{
void Initialize();
}
}

View File

@@ -0,0 +1,15 @@
#include "../../Includes.hpp"
// C+P Ready Template
namespace Unity
{
S_TEMPLATEFunctions _TEMPLATEFunctions;
namespace _TEMPLATE
{
void Initialize()
{
}
}
}

View File

@@ -0,0 +1,22 @@
#pragma once
// C+P Ready Template
namespace Unity
{
struct S_TEMPLATEFunctions
{
};
extern S_TEMPLATEFunctions _TEMPLATEFunctions;
class C_TEMPLATE : public IL2CPP::CClass
{
public:
};
namespace _TEMPLATE
{
void Initialize();
}
}

View File

@@ -0,0 +1,110 @@
#pragma once
// Calling Convention
#define UNITY_CALLING_CONVENTION __fastcall*
// Camera
#define UNITY_CAMERA_CLASS "UnityEngine.Camera"
#define UNITY_CAMERA_GETCURRENT UNITY_CAMERA_CLASS"::get_current"
#define UNITY_CAMERA_GETMAIN UNITY_CAMERA_CLASS"::get_main"
#define UNITY_CAMERA_GETDEPTH UNITY_CAMERA_CLASS"::get_depth"
#define UNITY_CAMERA_SETDEPTH UNITY_CAMERA_CLASS"::set_depth"
#define UNITY_CAMERA_GETFIELDOFVIEW UNITY_CAMERA_CLASS"::get_fieldOfView"
#define UNITY_CAMERA_SETFIELDOFVIEW UNITY_CAMERA_CLASS"::set_fieldOfView"
#define UNITY_CAMERA_WORLDTOSCREEN UNITY_CAMERA_CLASS"::WorldToScreenPoint_Injected"
// Component
#define UNITY_COMPONENT_CLASS "UnityEngine.Component"
#define UNITY_COMPONENT_GETGAMEOBJECT UNITY_COMPONENT_CLASS"::get_gameObject"
#define UNITY_COMPONENT_GETTRANSFORM UNITY_COMPONENT_CLASS"::get_transform"
// GameObject
#define UNITY_GAMEOBJECT_CLASS "UnityEngine.GameObject"
#define UNITY_GAMEOBJECT_ADDCOMPONENT UNITY_GAMEOBJECT_CLASS"::Internal_AddComponentWithType"
#define UNITY_GAMEOBJECT_CREATEPRIMITIVE UNITY_GAMEOBJECT_CLASS"::CreatePrimitive"
#define UNITY_GAMEOBJECT_FIND UNITY_GAMEOBJECT_CLASS"::Find"
#define UNITY_GAMEOBJECT_GETCOMPONENT UNITY_GAMEOBJECT_CLASS"::GetComponentByName"
#define UNITY_GAMEOBJECT_GETCOMPONENTS UNITY_GAMEOBJECT_CLASS"::GetComponentsInternal"
#define UNITY_GAMEOBJECT_GETACTIVE UNITY_GAMEOBJECT_CLASS"::get_active"
#define UNITY_GAMEOBJECT_GETLAYER UNITY_GAMEOBJECT_CLASS"::get_layer"
#define UNITY_GAMEOBJECT_GETTRANSFORM UNITY_GAMEOBJECT_CLASS"::get_transform"
#define UNITY_GAMEOBJECT_SETACTIVE UNITY_GAMEOBJECT_CLASS"::set_active"
#define UNITY_GAMEOBJECT_SETLAYER UNITY_GAMEOBJECT_CLASS"::set_layer"
#define UNITY_GAMEOBJECT_FINDGAMEOBJECTWITHTAG UNITY_GAMEOBJECT_CLASS"::FindGameObjectsWithTag"
// LayerMask
#define UNITY_LAYERMASK_CLASS "UnityEngine.LayerMask"
#define UNITY_LAYERMASK_LAYERTONAME UNITY_LAYERMASK_CLASS"::LayerToName"
#define UNITY_LAYERMASK_NAMETOLAYER UNITY_LAYERMASK_CLASS"::NameToLayer"
// MonoBehaviour
#define UNITY_MONOBEHAVIOUR_CLASS "UnityEngine.MonoBehaviour"
// Object
#define UNITY_OBJECT_CLASS "UnityEngine.Object"
#define UNITY_OBJECT_DESTROY UNITY_OBJECT_CLASS"::Destroy"
#define UNITY_OBJECT_FINDOBJECTSOFTYPE UNITY_OBJECT_CLASS"::FindObjectsOfType"
#define UNITY_OBJECT_GETNAME UNITY_OBJECT_CLASS"::GetName"
// Rigidbody
#define UNITY_RIGIDBODY_CLASS "UnityEngine.Rigidbody"
#define UNITY_RIGIDBODY_GETDETECTCOLLISIONS UNITY_RIGIDBODY_CLASS"::get_detectCollisions"
#define UNITY_RIGIDBODY_GETVELOCITY UNITY_RIGIDBODY_CLASS"::get_velocity_Injected"
#define UNITY_RIGIDBODY_SETDETECTCOLLISIONS UNITY_RIGIDBODY_CLASS"::set_detectCollisions"
#define UNITY_RIGIDBODY_SETVELOCITY UNITY_RIGIDBODY_CLASS"::set_velocity_Injected"
// Transform
#define UNITY_TRANSFORM_CLASS "UnityEngine.Transform"
#define UNITY_TRANSFORM_GETPARENT UNITY_TRANSFORM_CLASS"::GetParent"
#define UNITY_TRANSFORM_GETROOT UNITY_TRANSFORM_CLASS"::GetRoot"
#define UNITY_TRANSFORM_GETCHILD UNITY_TRANSFORM_CLASS"::GetChild"
#define UNITY_TRANSFORM_GETCHILDCOUNT UNITY_TRANSFORM_CLASS"::get_childCount"
#define UNITY_TRANSFORM_GETPOSITION UNITY_TRANSFORM_CLASS"::get_position_Injected"
#define UNITY_TRANSFORM_GETROTATION UNITY_TRANSFORM_CLASS"::get_rotation_Injected"
#define UNITY_TRANSFORM_GETLOCALPOSITION UNITY_TRANSFORM_CLASS"::get_localPosition_Injected"
#define UNITY_TRANSFORM_GETLOCALSCALE UNITY_TRANSFORM_CLASS"::get_localScale_Injected"
#define UNITY_TRANSFORM_SETPOSITION UNITY_TRANSFORM_CLASS"::set_position_Injected"
#define UNITY_TRANSFORM_SETROTATION UNITY_TRANSFORM_CLASS"::set_rotation_Injected"
#define UNITY_TRANSFORM_SETLOCALPOSITION UNITY_TRANSFORM_CLASS"::set_localPosition_Injected"
#define UNITY_TRANSFORM_SETLOCALSCALE UNITY_TRANSFORM_CLASS"::set_localScale_Injected"
namespace Unity
{
enum m_eTypeEnum
{
Type_Void = 1,
Type_Boolean = 2,
Type_Character = 3,
Type_Integer = 8,
Type_Float = 12,
Type_String = 14,
Type_Pointer = 15,
Type_ValueType = 17,
Type_Class = 18,
Type_Variable = 19,
Type_Array = 20,
Type_Enum = 85,
};
enum m_eFieldAttribute
{
FieldAttribute_Compiler,
FieldAttribute_Private,
FieldAttribute_FamilyAndAssembly,
FieldAttribute_Assembly,
FieldAttribute_Family,
FieldAttribute_FamilyOrAssembly,
FieldAttribute_Public,
FieldAttribute_AccessMask,
FieldAttribute_Static = 16,
FieldAttribute_InitOnly = 32,
FieldAttribute_Literal = 64,
FieldAttribute_NotSerialized = 128,
FieldAttribute_HasRVA = 256,
FieldAttribute_SpecialName = 512,
FieldAttribute_RTSpecialName = 1024,
FieldAttribute_HasMarshal = 4096,
FieldAttribute_InvokeImpl = 8192,
FieldAttribute_Default = 32768,
FieldAttribute_Reserved = 38144,
};
}

View File

@@ -0,0 +1,17 @@
#pragma once
#include "Defines.hpp"
#include "Obfuscators.hpp"
// Structures
#include "Structures/Includes.hpp"
// Class APIs - So they're accessible everywhere
namespace Unity
{
class CCamera;
class CComponent;
class CGameObject;
class CObject;
class CRigidbody;
class CTransform;
}

View File

@@ -0,0 +1,41 @@
#include "../Includes.hpp"
namespace Unity
{
namespace Obfuscators
{
// Should do the basic work
std::string ROT_String(const char* pString, int iValue)
{
std::string sRet;
size_t sSize = strlen(pString);
for (size_t i = 0; sSize > i; ++i)
{
bool bIsUppercase = pString[i] >= 'A' && 'Z' >= pString[i];
bool bIsLowercase = !bIsUppercase && pString[i] >= 'a' && 'z' >= pString[i];
if (!bIsUppercase && !bIsLowercase)
{
sRet += pString[i];
continue;
}
int iNewValue = static_cast<int>(pString[i]) + iValue;
if (bIsUppercase)
{
int iMaxValue = static_cast<int>('Z');
while (iNewValue > iMaxValue) iNewValue = static_cast<int>('A') + (iNewValue - iMaxValue);
}
else
{
int iMaxValue = static_cast<int>('z');
while (iNewValue > iMaxValue) iNewValue = static_cast<int>('a') + (iNewValue - iMaxValue);
}
sRet += static_cast<char>(iNewValue);
}
sRet += '\0';
return sRet;
}
}
}

View File

@@ -0,0 +1,9 @@
#pragma once
namespace Unity
{
namespace Obfuscators
{
std::string ROT_String(const char* pString, int iValue);
}
}

View File

@@ -0,0 +1,179 @@
#pragma once
namespace Unity
{
struct Vector2
{
float x, y;
Vector2() { x = y = 0.f; }
Vector2(float f1, float f2) { x = f1; y = f2; }
};
struct Vector3
{
float x, y, z;
Vector3() { x = y = z = 0.f; }
Vector3(float f1, float f2, float f3) { x = f1; y = f2; z = f3; }
void ToVectors(Vector3* m_pForward, Vector3* m_pRight, Vector3* m_pUp)
{
float m_fDeg2Rad = static_cast<float>(M_PI) / 180.f;
float m_fSinX = sinf(x * m_fDeg2Rad);
float m_fCosX = cosf(x * m_fDeg2Rad);
float m_fSinY = sinf(y * m_fDeg2Rad);
float m_fCosY = cosf(y * m_fDeg2Rad);
float m_fSinZ = sinf(z * m_fDeg2Rad);
float m_fCosZ = cosf(z * m_fDeg2Rad);
if (m_pForward)
{
m_pForward->x = m_fCosX * m_fCosY;
m_pForward->y = -m_fSinX;
m_pForward->z = m_fCosX * m_fSinY;
}
if (m_pRight)
{
m_pRight->x = -1.f * m_fSinZ * m_fSinX * m_fCosY + -1.f * m_fCosZ * -m_fSinY;
m_pRight->y = -1.f * m_fSinZ * m_fCosX;
m_pRight->z = -1.f * m_fSinZ * m_fSinX * m_fSinY + -1.f * m_fCosZ * m_fCosY;
}
if (m_pUp)
{
m_pUp->x = m_fCosZ * m_fSinX * m_fCosY + -m_fSinZ * -m_fSinY;
m_pUp->y = m_fCosZ * m_fCosX;
m_pUp->z = m_fCosZ * m_fSinX * m_fSinY + -m_fSinZ * m_fCosY;
}
}
};
struct Vector4
{
float x, y, z, w;
Vector4() { x = y = z = w = 0.f; }
Vector4(float f1, float f2, float f3, float f4) { x = f1; y = f2; z = f3; w = f4; }
};
struct Quaternion
{
float x, y, z, w;
Quaternion() { x = y = z = w = 0.f; }
Quaternion(float f1, float f2, float f3, float f4) { x = f1; y = f2; z = f3; w = f4; }
Quaternion Euler(float m_fX, float m_fY, float m_fZ)
{
float m_fDeg2Rad = static_cast<float>(M_PI) / 180.f;
m_fX = m_fX * m_fDeg2Rad * 0.5f;
m_fY = m_fY * m_fDeg2Rad * 0.5f;
m_fZ = m_fZ * m_fDeg2Rad * 0.5f;
float m_fSinX = sinf(m_fX);
float m_fCosX = cosf(m_fX);
float m_fSinY = sinf(m_fY);
float m_fCosY = cosf(m_fY);
float m_fSinZ = sinf(m_fZ);
float m_fCosZ = cosf(m_fZ);
x = m_fCosY * m_fSinX * m_fCosZ + m_fSinY * m_fCosX * m_fSinZ;
y = m_fSinY * m_fCosX * m_fCosZ - m_fCosY * m_fSinX * m_fSinZ;
z = m_fCosY * m_fCosX * m_fSinZ - m_fSinY * m_fSinX * m_fCosZ;
w = m_fCosY * m_fCosX * m_fCosZ + m_fSinY * m_fSinX * m_fSinZ;
return *this;
}
Quaternion Euler(Vector3 m_vRot)
{
return Euler(m_vRot.x, m_vRot.y, m_vRot.z);
}
Vector3 ToEuler()
{
Vector3 m_vEuler;
float m_fDist = (x * x) + (y * y) + (z * z) + (w * w);
float m_fTest = x * w - y * z;
if (m_fTest > 0.4995f * m_fDist)
{
m_vEuler.x = static_cast<float>(M_PI) * 0.5f;
m_vEuler.y = 2.f * atan2f(y, x);
m_vEuler.z = 0.f;
}
else if (m_fTest < -0.4995f * m_fDist)
{
m_vEuler.x = static_cast<float>(M_PI) * -0.5f;
m_vEuler.y = -2.f * atan2f(y, x);
m_vEuler.z = 0.f;
}
else
{
m_vEuler.x = asinf(2.f * (w * x - y * z));
m_vEuler.y = atan2f(2.f * w * y + 2.f * z * x, 1.f - 2.f * (x * x + y * y));
m_vEuler.z = atan2f(2.f * w * z + 2.f * x * y, 1.f - 2.f * (z * z + x * x));
}
float m_fRad2Deg = 180.f / static_cast<float>(M_PI);
m_vEuler.x *= m_fRad2Deg;
m_vEuler.y *= m_fRad2Deg;
m_vEuler.z *= m_fRad2Deg;
return m_vEuler;
}
};
struct Bounds
{
Vector3 m_vCenter;
Vector3 m_vExtents;
};
struct Plane
{
Vector3 m_vNormal;
float fDistance;
};
struct Ray
{
Vector3 m_vOrigin;
Vector3 m_vDirection;
};
struct Rect
{
float fX, fY;
float fWidth, fHeight;
Rect() { fX = fY = fWidth = fHeight = 0.f; }
Rect(float f1, float f2, float f3, float f4) { fX = f1; fY = f2; fWidth = f3; fHeight = f4; }
};
struct Color
{
float r, g, b, a;
Color() { r = g = b = a = 0.f; }
Color(float fRed = 0.f, float fGreen = 0.f, float fBlue = 0.f, float fAlpha = 1.f) { r = fRed; g = fGreen; b = fBlue; a = fAlpha; }
};
struct Matrix4x4
{
float m[4][4] = { 0 };
Matrix4x4() { }
float* operator[](int i) { return m[i]; }
};
}

View File

@@ -0,0 +1,7 @@
#pragma once
#include "il2cpp.hpp"
#include "il2cppArray.hpp"
#include "il2cppDictionary.hpp"
#include "Engine.hpp"
#include "System_String.hpp"

View File

@@ -0,0 +1,27 @@
#pragma once
namespace Unity
{
struct System_String : il2cppObject
{
int m_iLength;
wchar_t m_wString[1024];
void Clear()
{
if (!this) return;
memset(m_wString, 0, static_cast<size_t>(m_iLength) * 2);
m_iLength = 0;
}
std::string ToString()
{
if (!this) return "";
std::string sRet(static_cast<size_t>(m_iLength) + 1, '\0');
WideCharToMultiByte(CP_UTF8, 0, m_wString, m_iLength, &sRet[0], m_iLength, 0, 0);
return sRet;
}
};
}

View File

@@ -0,0 +1,151 @@
#pragma once
namespace Unity
{
struct il2cppImage
{
const char* m_pName;
const char* m_pNameNoExt;
};
struct il2cppAssemblyName
{
const char* m_pName;
const char* m_pCulture;
const char* m_pHash;
const char* m_pPublicKey;
unsigned int m_uHash;
int m_iHashLength;
unsigned int m_uFlags;
int m_iMajor;
int m_iMinor;
int m_iBuild;
int m_bRevision;
unsigned char m_uPublicKeyToken[8];
};
struct il2cppAssembly
{
il2cppImage* m_pImage;
unsigned int m_uToken;
int m_ReferencedAssemblyStart;
int m_ReferencedAssemblyCount;
il2cppAssemblyName m_aName;
};
struct il2cppClass
{
void* m_pImage;
void* m_pGC;
const char* m_pName;
const char* m_pNamespace;
void* m_pValue;
void* m_pArgs;
il2cppClass* m_pElementClass;
il2cppClass* m_pCastClass;
il2cppClass* m_pDeclareClass;
il2cppClass* m_pParentClass;
void* m_pGenericClass;
void* m_pTypeDefinition;
void* m_pInteropData;
void* m_pFields;
void* m_pEvents;
void* m_pProperties;
void** m_pMethods;
il2cppClass** m_pNestedTypes;
il2cppClass** m_ImplementedInterfaces;
void* m_pInterfaceOffsets;
void* m_pStaticFields;
void* m_pRGCTX;
};
struct il2cppObject
{
il2cppClass* m_pClass = nullptr;
void* m_pMonitor = nullptr;
};
struct il2cppType
{
union
{
void* m_pDummy;
unsigned int m_uClassIndex;
il2cppType* m_pType;
void* m_pArray;
unsigned int m_uGenericParameterIndex;
void* m_pGenericClass;
};
unsigned int m_uAttributes : 16;
unsigned int m_uType : 8;
unsigned int m_uMods : 6;
unsigned int m_uByref : 1;
unsigned int m_uPinned : 1;
};
struct il2cppFieldInfo
{
const char* m_pName;
il2cppType* m_pType;
il2cppClass* m_pParentClass;
int m_iOffset;
int m_iAttributeIndex;
unsigned int m_uToken;
};
struct il2cppParameterInfo
{
const char* m_pName;
int m_iPosition;
unsigned int m_uToken;
il2cppType* m_pParameterType;
};
struct il2cppMethodInfo
{
void* m_pMethodPointer;
void* m_pInvokerMethod;
const char* m_pName;
il2cppClass* m_pClass;
il2cppType* m_pReturnType;
il2cppParameterInfo* m_pParameters;
union
{
void* m_pRGCTX;
void* m_pMethodDefinition;
};
union
{
void* m_pGenericMethod;
void* m_pGenericContainer;
};
unsigned int m_uToken;
unsigned short m_uFlags;
unsigned short m_uFlags2;
unsigned short m_uSlot;
unsigned char m_uArgsCount;
unsigned char m_uGeneric : 1;
unsigned char m_uInflated : 1;
unsigned char m_uWrapperType : 1;
unsigned char m_uMarshaledFromNative : 1;
};
struct il2cppPropertyInfo
{
il2cppClass* m_pParentClass;
const char* m_pName;
il2cppMethodInfo* m_pGet;
il2cppMethodInfo* m_pSet;
unsigned int m_uAttributes;
unsigned int m_uToken;
};
struct il2cppArrayBounds
{
uintptr_t m_uLength;
int m_iLowerBound;
};
}

View File

@@ -0,0 +1,97 @@
#pragma once
namespace Unity
{
template<typename T>
struct il2cppArray : il2cppObject
{
il2cppArrayBounds* m_pBounds = nullptr;
uintptr_t m_uMaxLength = 0;
T* m_pValues = nullptr;
uintptr_t GetData()
{
return reinterpret_cast<uintptr_t>(&m_pValues);
}
T& operator[](unsigned int m_uIndex)
{
return *reinterpret_cast<T*>(GetData() + sizeof(T) * m_uIndex);
}
T& At(unsigned int m_uIndex)
{
return operator[](m_uIndex);
}
void Insert(T* m_pArray, uintptr_t m_uSize, uintptr_t m_uIndex = 0)
{
if ((m_uSize + m_uIndex) >= m_uMaxLength)
{
if (m_uIndex >= m_uMaxLength)
return;
m_uSize = m_uMaxLength - m_uIndex;
}
for (uintptr_t u = 0; m_uSize > u; ++u)
operator[](u + m_uIndex) = m_pArray[u];
}
void Fill(T m_tValue)
{
for (uintptr_t u = 0; m_uMaxLength > u; ++u)
operator[](u) = m_tValue;
}
void RemoveAt(unsigned int m_uIndex)
{
if (m_uIndex >= m_uMaxLength)
return;
if (m_uMaxLength > (m_uIndex + 1))
{
for (unsigned int u = m_uIndex; (static_cast<unsigned int>(m_uMaxLength) - m_uIndex) > u; ++u)
operator[](u) = operator[](u + 1);
}
--m_uMaxLength;
}
void RemoveRange(unsigned int m_uIndex, unsigned int m_uCount)
{
if (m_uCount == 0)
m_uCount = 1;
unsigned int m_uTotal = m_uIndex + m_uCount;
if (m_uTotal >= m_uMaxLength)
return;
if (m_uMaxLength > (m_uTotal + 1))
{
for (unsigned int u = m_uIndex; (static_cast<unsigned int>(m_uMaxLength) - m_uTotal) >= u; ++u)
operator[](u) = operator[](u + m_uCount);
}
m_uMaxLength -= m_uCount;
}
void RemoveAll()
{
if (m_uMaxLength > 0)
{
memset(GetData(), 0, sizeof(T) * m_uMaxLength);
m_uMaxLength = 0;
}
}
};
// Defined here because its basically same shit
template<typename T>
struct il2cppList : il2cppObject
{
il2cppArray<T>* m_pListArray;
il2cppArray<T>* ToArray() { return m_pListArray; }
};
}

View File

@@ -0,0 +1,19 @@
#pragma once
namespace Unity
{
// Don't use! Untested
template<typename T>
struct il2cppDictionary : il2cppObject
{
il2cppArray<int>* m_pBuckets;
il2cppArray<T>* m_pEntries;
int m_iCount;
int m_iVersion;
int m_iFreeList;
int m_iFreeCount;
void* m_pComparer;
void* m_pKeys;
void* m_pValues;
};
}

View File

@@ -0,0 +1,23 @@
#include "../Includes.hpp"
namespace IL2CPP
{
namespace Helper
{
Unity::CComponent* GetMonoBehaviour()
{
Unity::il2cppArray<Unity::CGameObject*>* m_pObjects = Unity::Object::FindObjectsOfType<Unity::CGameObject>(UNITY_GAMEOBJECT_CLASS);
for (uintptr_t u = 0U; m_pObjects->m_uMaxLength > u; ++u)
{
Unity::CGameObject* m_pObject = m_pObjects->operator[](static_cast<unsigned int>(u));
if (!m_pObject) continue;
Unity::CComponent* m_pMonoBehaviour = m_pObject->GetComponentByIndex(UNITY_MONOBEHAVIOUR_CLASS);
if (m_pMonoBehaviour)
return m_pMonoBehaviour;
}
return nullptr;
}
}
}

View File

@@ -0,0 +1,9 @@
#pragma once
namespace IL2CPP
{
namespace Helper
{
Unity::CComponent* GetMonoBehaviour();
}
}

View File

@@ -0,0 +1,43 @@
#pragma once
namespace IL2CPP
{
namespace Utils
{
inline unsigned int JOAAT(const char* str)
{
unsigned int m_uHash = 0;
while (*str)
{
m_uHash += *(str++);
m_uHash += (m_uHash << 10);
m_uHash ^= (m_uHash >> 6);
}
m_uHash += (m_uHash << 3);
m_uHash ^= (m_uHash >> 11);
m_uHash += (m_uHash << 15);
return m_uHash;
}
inline constexpr unsigned int JOAAT_CONSTEXPR(const char* str)
{
unsigned int m_uHash = 0;
while (*str)
{
m_uHash += *(str++);
m_uHash += (m_uHash << 10);
m_uHash ^= (m_uHash >> 6);
}
m_uHash += (m_uHash << 3);
m_uHash ^= (m_uHash >> 11);
m_uHash += (m_uHash << 15);
return m_uHash;
}
}
}

View File

@@ -0,0 +1,31 @@
#pragma once
namespace VFunc
{
static void** Find_ASM(void** m_pVTable, int m_iCount, std::initializer_list<unsigned char> m_lASM)
{
int m_iASMSize = static_cast<int>(m_lASM.size());
unsigned char* m_pBytes = const_cast<unsigned char*>(m_lASM.begin());
for (int i = 0; m_iCount > i; ++i)
{
void* m_pVFunc = m_pVTable[i];
unsigned char* m_pVFuncBytes = reinterpret_cast<unsigned char*>(m_pVFunc);
bool m_bAllMatch = true;
for (int b = 0; m_iASMSize > b; ++b)
{
if (m_pBytes[b] != m_pVFuncBytes[b])
{
m_bAllMatch = false;
break;
}
}
if (m_bAllMatch)
return &m_pVTable[i];
}
return 0;
}
}

View File

@@ -0,0 +1,125 @@
#include "il2cpp_resolver.hpp"
namespace IL2CPP
{
bool Initialize(bool m_bWaitForModule)
{
if (m_bWaitForModule)
{
while (!Data.m_hGameAseembly)
{
Data.m_hGameAseembly = GetModuleHandleA(IL2CPP_MAIN_MODULE);
Sleep(1000); // Prevent high CPU usage!
}
}
else
{
Data.m_hGameAseembly = GetModuleHandleA(IL2CPP_MAIN_MODULE);
if (!Data.m_hGameAseembly) return false;
}
if (!UnityAPI::Initialize()) return false;
return true;
}
namespace UnityAPI
{
m_eExportObfuscationType m_ExportObfuscation = m_eExportObfuscationType::None;
int m_iROTObfuscationValue = -1;
void* ResolveExport(const char* m_pName)
{
switch (m_ExportObfuscation)
{
case m_eExportObfuscationType::ROT:
{
if (m_iROTObfuscationValue == -1) // Bruteforce
{
for (int i = 1; 26 > i; ++i)
{
void* pReturn = GetProcAddress(Data.m_hGameAseembly, &Unity::Obfuscators::ROT_String(m_pName, i)[0]);
if (pReturn)
{
m_iROTObfuscationValue = i;
return pReturn;
}
}
return nullptr;
}
return GetProcAddress(Data.m_hGameAseembly, &Unity::Obfuscators::ROT_String(m_pName, m_iROTObfuscationValue)[0]);
}
default: return GetProcAddress(Data.m_hGameAseembly, m_pName);
}
return nullptr;
}
bool ResolveExport_Boolean(void** m_pAddress, const char* m_pName)
{
*m_pAddress = ResolveExport(m_pName);
IL2CPP_ASSERT(*m_pAddress != nullptr && "Couldn't resolve export!");
return *m_pAddress != nullptr;
}
bool Initialize()
{
bool m_bInitExportResolved = false;
for (int i = 0; m_eExportObfuscationType::MAX > i; ++i)
{
m_ExportObfuscation = static_cast<m_eExportObfuscationType>(i);
if (ResolveExport(IL2CPP_INIT_EXPORT))
{
m_bInitExportResolved = true;
break;
}
}
IL2CPP_ASSERT(m_bInitExportResolved && "Couldn't resolve il2cpp_init!");
if (!m_bInitExportResolved) return false;
std::unordered_map<const char*, void**> m_uExports =
{
{ IL2CPP_CLASS_FROM_NAME_EXPORT, &Data.Functions.m_pClassFromName },
{ IL2CPP_CLASS_GET_FIELDS, &Data.Functions.m_pClassGetFields },
{ IL2CPP_CLASS_GET_FIELD_FROM_NAME_EXPORT, &Data.Functions.m_pClassGetFieldFromName },
{ IL2CPP_CLASS_GET_METHODS, &Data.Functions.m_pClassGetMethods },
{ IL2CPP_CLASS_GET_METHOD_FROM_NAME_EXPORT, &Data.Functions.m_pClassGetMethodFromName },
{ IL2CPP_CLASS_GET_PROPERTY_FROM_NAME_EXPORT, &Data.Functions.m_pClassGetPropertyFromName },
{ IL2CPP_CLASS_GET_TYPE_EXPORT, &Data.Functions.m_pClassGetType },
{ IL2CPP_DOMAIN_GET_EXPORT, &Data.Functions.m_pDomainGet },
{ IL2CPP_DOMAIN_GET_ASSEMBLIES_EXPORT, &Data.Functions.m_pDomainGetAssemblies },
{ IL2CPP_FREE_EXPORT, &Data.Functions.m_pFree },
{ IL2CPP_IMAGE_GET_CLASS_EXPORT, &Data.Functions.m_pImageGetClass },
{ IL2CPP_IMAGE_GET_CLASS_COUNT_EXPORT, &Data.Functions.m_pImageGetClassCount },
{ IL2CPP_RESOLVE_FUNC_EXPORT, &Data.Functions.m_pResolveFunction },
{ IL2CPP_STRING_NEW_EXPORT, &Data.Functions.m_pStringNew },
{ IL2CPP_THREAD_ATTACH_EXPORT, &Data.Functions.m_pThreadAttach },
{ IL2CPP_THREAD_DETACH_EXPORT, &Data.Functions.m_pThreadDetach },
{ IL2CPP_TYPE_GET_OBJECT_EXPORT, &Data.Functions.m_pTypeGetObject },
};
for (std::pair<const char*, void**> m_pExport : m_uExports)
{
if (!ResolveExport_Boolean(m_pExport.second, m_pExport.first))
return false;
}
// Unity APIs
Unity::Camera::Initialize();
Unity::Component::Initialize();
Unity::GameObject::Initialize();
Unity::LayerMask::Initialize();
Unity::Object::Initialize();
Unity::RigidBody::Initialize();
Unity::Transform::Initialize();
// Caches
IL2CPP::SystemTypeCache::Initializer::PreCache();
return true;
}
}
}

View File

@@ -0,0 +1,27 @@
#pragma once
#include "Includes.hpp"
namespace IL2CPP
{
/* Must be called once before using any other functions!
* Args:
* bWaitForModule: (Wait for GameAssembly - can result in infinite loop!)
*/
bool Initialize(bool m_bWaitForModule = false);
namespace UnityAPI
{
enum m_eExportObfuscationType
{
None = 0,
ROT = 1,
MAX = 2,
};
extern m_eExportObfuscationType m_ExportObfuscation;
void* ResolveExport(const char* m_pName);
bool Initialize();
}
}

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,185 @@
/*
* MinHook - The Minimalistic API Hooking Library for x64/x86
* Copyright (C) 2009-2017 Tsuda Kageyu.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__)
#error MinHook supports only x86 and x64 systems.
#endif
#include <windows.h>
// MinHook Error Codes.
typedef enum MH_STATUS
{
// Unknown error. Should not be returned.
MH_UNKNOWN = -1,
// Successful.
MH_OK = 0,
// MinHook is already initialized.
MH_ERROR_ALREADY_INITIALIZED,
// MinHook is not initialized yet, or already uninitialized.
MH_ERROR_NOT_INITIALIZED,
// The hook for the specified target function is already created.
MH_ERROR_ALREADY_CREATED,
// The hook for the specified target function is not created yet.
MH_ERROR_NOT_CREATED,
// The hook for the specified target function is already enabled.
MH_ERROR_ENABLED,
// The hook for the specified target function is not enabled yet, or already
// disabled.
MH_ERROR_DISABLED,
// The specified pointer is invalid. It points the address of non-allocated
// and/or non-executable region.
MH_ERROR_NOT_EXECUTABLE,
// The specified target function cannot be hooked.
MH_ERROR_UNSUPPORTED_FUNCTION,
// Failed to allocate memory.
MH_ERROR_MEMORY_ALLOC,
// Failed to change the memory protection.
MH_ERROR_MEMORY_PROTECT,
// The specified module is not loaded.
MH_ERROR_MODULE_NOT_FOUND,
// The specified function is not found.
MH_ERROR_FUNCTION_NOT_FOUND
}
MH_STATUS;
// Can be passed as a parameter to MH_EnableHook, MH_DisableHook,
// MH_QueueEnableHook or MH_QueueDisableHook.
#define MH_ALL_HOOKS NULL
#ifdef __cplusplus
extern "C" {
#endif
// Initialize the MinHook library. You must call this function EXACTLY ONCE
// at the beginning of your program.
MH_STATUS WINAPI MH_Initialize(VOID);
// Uninitialize the MinHook library. You must call this function EXACTLY
// ONCE at the end of your program.
MH_STATUS WINAPI MH_Uninitialize(VOID);
// Creates a hook for the specified target function, in disabled state.
// Parameters:
// pTarget [in] A pointer to the target function, which will be
// overridden by the detour function.
// pDetour [in] A pointer to the detour function, which will override
// the target function.
// ppOriginal [out] A pointer to the trampoline function, which will be
// used to call the original target function.
// This parameter can be NULL.
MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal);
// Creates a hook for the specified API function, in disabled state.
// Parameters:
// pszModule [in] A pointer to the loaded module name which contains the
// target function.
// pszProcName [in] A pointer to the target function name, which will be
// overridden by the detour function.
// pDetour [in] A pointer to the detour function, which will override
// the target function.
// ppOriginal [out] A pointer to the trampoline function, which will be
// used to call the original target function.
// This parameter can be NULL.
MH_STATUS WINAPI MH_CreateHookApi(
LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal);
// Creates a hook for the specified API function, in disabled state.
// Parameters:
// pszModule [in] A pointer to the loaded module name which contains the
// target function.
// pszProcName [in] A pointer to the target function name, which will be
// overridden by the detour function.
// pDetour [in] A pointer to the detour function, which will override
// the target function.
// ppOriginal [out] A pointer to the trampoline function, which will be
// used to call the original target function.
// This parameter can be NULL.
// ppTarget [out] A pointer to the target function, which will be used
// with other functions.
// This parameter can be NULL.
MH_STATUS WINAPI MH_CreateHookApiEx(
LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget);
// Removes an already created hook.
// Parameters:
// pTarget [in] A pointer to the target function.
MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget);
// Enables an already created hook.
// Parameters:
// pTarget [in] A pointer to the target function.
// If this parameter is MH_ALL_HOOKS, all created hooks are
// enabled in one go.
MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget);
// Disables an already created hook.
// Parameters:
// pTarget [in] A pointer to the target function.
// If this parameter is MH_ALL_HOOKS, all created hooks are
// disabled in one go.
MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget);
// Queues to enable an already created hook.
// Parameters:
// pTarget [in] A pointer to the target function.
// If this parameter is MH_ALL_HOOKS, all created hooks are
// queued to be enabled.
MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget);
// Queues to disable an already created hook.
// Parameters:
// pTarget [in] A pointer to the target function.
// If this parameter is MH_ALL_HOOKS, all created hooks are
// queued to be disabled.
MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget);
// Applies all queued changes in one go.
MH_STATUS WINAPI MH_ApplyQueued(VOID);
// Translates the MH_STATUS to its name as a string.
const char * WINAPI MH_StatusToString(MH_STATUS status);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,324 @@
/*
* Hacker Disassembler Engine 32 C
* Copyright (c) 2008-2009, Vyacheslav Patkov.
* All rights reserved.
*
*/
#if defined(_M_IX86) || defined(__i386__)
#include <string.h>
#include "hde32.h"
#include "table32.h"
unsigned int hde32_disasm(const void *code, hde32s *hs)
{
uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0;
uint8_t *ht = hde32_table, m_mod, m_reg, m_rm, disp_size = 0;
memset(hs, 0, sizeof(hde32s));
for (x = 16; x; x--)
switch (c = *p++) {
case 0xf3:
hs->p_rep = c;
pref |= PRE_F3;
break;
case 0xf2:
hs->p_rep = c;
pref |= PRE_F2;
break;
case 0xf0:
hs->p_lock = c;
pref |= PRE_LOCK;
break;
case 0x26: case 0x2e: case 0x36:
case 0x3e: case 0x64: case 0x65:
hs->p_seg = c;
pref |= PRE_SEG;
break;
case 0x66:
hs->p_66 = c;
pref |= PRE_66;
break;
case 0x67:
hs->p_67 = c;
pref |= PRE_67;
break;
default:
goto pref_done;
}
pref_done:
hs->flags = (uint32_t)pref << 23;
if (!pref)
pref |= PRE_NONE;
if ((hs->opcode = c) == 0x0f) {
hs->opcode2 = c = *p++;
ht += DELTA_OPCODES;
} else if (c >= 0xa0 && c <= 0xa3) {
if (pref & PRE_67)
pref |= PRE_66;
else
pref &= ~PRE_66;
}
opcode = c;
cflags = ht[ht[opcode / 4] + (opcode % 4)];
if (cflags == C_ERROR) {
hs->flags |= F_ERROR | F_ERROR_OPCODE;
cflags = 0;
if ((opcode & -3) == 0x24)
cflags++;
}
x = 0;
if (cflags & C_GROUP) {
uint16_t t;
t = *(uint16_t *)(ht + (cflags & 0x7f));
cflags = (uint8_t)t;
x = (uint8_t)(t >> 8);
}
if (hs->opcode2) {
ht = hde32_table + DELTA_PREFIXES;
if (ht[ht[opcode / 4] + (opcode % 4)] & pref)
hs->flags |= F_ERROR | F_ERROR_OPCODE;
}
if (cflags & C_MODRM) {
hs->flags |= F_MODRM;
hs->modrm = c = *p++;
hs->modrm_mod = m_mod = c >> 6;
hs->modrm_rm = m_rm = c & 7;
hs->modrm_reg = m_reg = (c & 0x3f) >> 3;
if (x && ((x << m_reg) & 0x80))
hs->flags |= F_ERROR | F_ERROR_OPCODE;
if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) {
uint8_t t = opcode - 0xd9;
if (m_mod == 3) {
ht = hde32_table + DELTA_FPU_MODRM + t*8;
t = ht[m_reg] << m_rm;
} else {
ht = hde32_table + DELTA_FPU_REG;
t = ht[t] << m_reg;
}
if (t & 0x80)
hs->flags |= F_ERROR | F_ERROR_OPCODE;
}
if (pref & PRE_LOCK) {
if (m_mod == 3) {
hs->flags |= F_ERROR | F_ERROR_LOCK;
} else {
uint8_t *table_end, op = opcode;
if (hs->opcode2) {
ht = hde32_table + DELTA_OP2_LOCK_OK;
table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK;
} else {
ht = hde32_table + DELTA_OP_LOCK_OK;
table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK;
op &= -2;
}
for (; ht != table_end; ht++)
if (*ht++ == op) {
if (!((*ht << m_reg) & 0x80))
goto no_lock_error;
else
break;
}
hs->flags |= F_ERROR | F_ERROR_LOCK;
no_lock_error:
;
}
}
if (hs->opcode2) {
switch (opcode) {
case 0x20: case 0x22:
m_mod = 3;
if (m_reg > 4 || m_reg == 1)
goto error_operand;
else
goto no_error_operand;
case 0x21: case 0x23:
m_mod = 3;
if (m_reg == 4 || m_reg == 5)
goto error_operand;
else
goto no_error_operand;
}
} else {
switch (opcode) {
case 0x8c:
if (m_reg > 5)
goto error_operand;
else
goto no_error_operand;
case 0x8e:
if (m_reg == 1 || m_reg > 5)
goto error_operand;
else
goto no_error_operand;
}
}
if (m_mod == 3) {
uint8_t *table_end;
if (hs->opcode2) {
ht = hde32_table + DELTA_OP2_ONLY_MEM;
table_end = ht + sizeof(hde32_table) - DELTA_OP2_ONLY_MEM;
} else {
ht = hde32_table + DELTA_OP_ONLY_MEM;
table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM;
}
for (; ht != table_end; ht += 2)
if (*ht++ == opcode) {
if ((*ht++ & pref) && !((*ht << m_reg) & 0x80))
goto error_operand;
else
break;
}
goto no_error_operand;
} else if (hs->opcode2) {
switch (opcode) {
case 0x50: case 0xd7: case 0xf7:
if (pref & (PRE_NONE | PRE_66))
goto error_operand;
break;
case 0xd6:
if (pref & (PRE_F2 | PRE_F3))
goto error_operand;
break;
case 0xc5:
goto error_operand;
}
goto no_error_operand;
} else
goto no_error_operand;
error_operand:
hs->flags |= F_ERROR | F_ERROR_OPERAND;
no_error_operand:
c = *p++;
if (m_reg <= 1) {
if (opcode == 0xf6)
cflags |= C_IMM8;
else if (opcode == 0xf7)
cflags |= C_IMM_P66;
}
switch (m_mod) {
case 0:
if (pref & PRE_67) {
if (m_rm == 6)
disp_size = 2;
} else
if (m_rm == 5)
disp_size = 4;
break;
case 1:
disp_size = 1;
break;
case 2:
disp_size = 2;
if (!(pref & PRE_67))
disp_size <<= 1;
break;
}
if (m_mod != 3 && m_rm == 4 && !(pref & PRE_67)) {
hs->flags |= F_SIB;
p++;
hs->sib = c;
hs->sib_scale = c >> 6;
hs->sib_index = (c & 0x3f) >> 3;
if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1))
disp_size = 4;
}
p--;
switch (disp_size) {
case 1:
hs->flags |= F_DISP8;
hs->disp.disp8 = *p;
break;
case 2:
hs->flags |= F_DISP16;
hs->disp.disp16 = *(uint16_t *)p;
break;
case 4:
hs->flags |= F_DISP32;
hs->disp.disp32 = *(uint32_t *)p;
break;
}
p += disp_size;
} else if (pref & PRE_LOCK)
hs->flags |= F_ERROR | F_ERROR_LOCK;
if (cflags & C_IMM_P66) {
if (cflags & C_REL32) {
if (pref & PRE_66) {
hs->flags |= F_IMM16 | F_RELATIVE;
hs->imm.imm16 = *(uint16_t *)p;
p += 2;
goto disasm_done;
}
goto rel32_ok;
}
if (pref & PRE_66) {
hs->flags |= F_IMM16;
hs->imm.imm16 = *(uint16_t *)p;
p += 2;
} else {
hs->flags |= F_IMM32;
hs->imm.imm32 = *(uint32_t *)p;
p += 4;
}
}
if (cflags & C_IMM16) {
if (hs->flags & F_IMM32) {
hs->flags |= F_IMM16;
hs->disp.disp16 = *(uint16_t *)p;
} else if (hs->flags & F_IMM16) {
hs->flags |= F_2IMM16;
hs->disp.disp16 = *(uint16_t *)p;
} else {
hs->flags |= F_IMM16;
hs->imm.imm16 = *(uint16_t *)p;
}
p += 2;
}
if (cflags & C_IMM8) {
hs->flags |= F_IMM8;
hs->imm.imm8 = *p++;
}
if (cflags & C_REL32) {
rel32_ok:
hs->flags |= F_IMM32 | F_RELATIVE;
hs->imm.imm32 = *(uint32_t *)p;
p += 4;
} else if (cflags & C_REL8) {
hs->flags |= F_IMM8 | F_RELATIVE;
hs->imm.imm8 = *p++;
}
disasm_done:
if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) {
hs->flags |= F_ERROR | F_ERROR_LENGTH;
hs->len = 15;
}
return (unsigned int)hs->len;
}
#endif // defined(_M_IX86) || defined(__i386__)

View File

@@ -0,0 +1,105 @@
/*
* Hacker Disassembler Engine 32
* Copyright (c) 2006-2009, Vyacheslav Patkov.
* All rights reserved.
*
* hde32.h: C/C++ header file
*
*/
#ifndef _HDE32_H_
#define _HDE32_H_
/* stdint.h - C99 standard header
* http://en.wikipedia.org/wiki/stdint.h
*
* if your compiler doesn't contain "stdint.h" header (for
* example, Microsoft Visual C++), you can download file:
* http://www.azillionmonkeys.com/qed/pstdint.h
* and change next line to:
* #include "pstdint.h"
*/
#include "pstdint.h"
#define F_MODRM 0x00000001
#define F_SIB 0x00000002
#define F_IMM8 0x00000004
#define F_IMM16 0x00000008
#define F_IMM32 0x00000010
#define F_DISP8 0x00000020
#define F_DISP16 0x00000040
#define F_DISP32 0x00000080
#define F_RELATIVE 0x00000100
#define F_2IMM16 0x00000800
#define F_ERROR 0x00001000
#define F_ERROR_OPCODE 0x00002000
#define F_ERROR_LENGTH 0x00004000
#define F_ERROR_LOCK 0x00008000
#define F_ERROR_OPERAND 0x00010000
#define F_PREFIX_REPNZ 0x01000000
#define F_PREFIX_REPX 0x02000000
#define F_PREFIX_REP 0x03000000
#define F_PREFIX_66 0x04000000
#define F_PREFIX_67 0x08000000
#define F_PREFIX_LOCK 0x10000000
#define F_PREFIX_SEG 0x20000000
#define F_PREFIX_ANY 0x3f000000
#define PREFIX_SEGMENT_CS 0x2e
#define PREFIX_SEGMENT_SS 0x36
#define PREFIX_SEGMENT_DS 0x3e
#define PREFIX_SEGMENT_ES 0x26
#define PREFIX_SEGMENT_FS 0x64
#define PREFIX_SEGMENT_GS 0x65
#define PREFIX_LOCK 0xf0
#define PREFIX_REPNZ 0xf2
#define PREFIX_REPX 0xf3
#define PREFIX_OPERAND_SIZE 0x66
#define PREFIX_ADDRESS_SIZE 0x67
#pragma pack(push,1)
typedef struct {
uint8_t len;
uint8_t p_rep;
uint8_t p_lock;
uint8_t p_seg;
uint8_t p_66;
uint8_t p_67;
uint8_t opcode;
uint8_t opcode2;
uint8_t modrm;
uint8_t modrm_mod;
uint8_t modrm_reg;
uint8_t modrm_rm;
uint8_t sib;
uint8_t sib_scale;
uint8_t sib_index;
uint8_t sib_base;
union {
uint8_t imm8;
uint16_t imm16;
uint32_t imm32;
} imm;
union {
uint8_t disp8;
uint16_t disp16;
uint32_t disp32;
} disp;
uint32_t flags;
} hde32s;
#pragma pack(pop)
#ifdef __cplusplus
extern "C" {
#endif
/* __cdecl */
unsigned int hde32_disasm(const void *code, hde32s *hs);
#ifdef __cplusplus
}
#endif
#endif /* _HDE32_H_ */

View File

@@ -0,0 +1,333 @@
/*
* Hacker Disassembler Engine 64 C
* Copyright (c) 2008-2009, Vyacheslav Patkov.
* All rights reserved.
*
*/
#if defined(_M_X64) || defined(__x86_64__)
#include <string.h>
#include "hde64.h"
#include "table64.h"
unsigned int hde64_disasm(const void *code, hde64s *hs)
{
uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0;
uint8_t *ht = hde64_table, m_mod, m_reg, m_rm, disp_size = 0;
uint8_t op64 = 0;
memset(hs, 0, sizeof(hde64s));
for (x = 16; x; x--)
switch (c = *p++) {
case 0xf3:
hs->p_rep = c;
pref |= PRE_F3;
break;
case 0xf2:
hs->p_rep = c;
pref |= PRE_F2;
break;
case 0xf0:
hs->p_lock = c;
pref |= PRE_LOCK;
break;
case 0x26: case 0x2e: case 0x36:
case 0x3e: case 0x64: case 0x65:
hs->p_seg = c;
pref |= PRE_SEG;
break;
case 0x66:
hs->p_66 = c;
pref |= PRE_66;
break;
case 0x67:
hs->p_67 = c;
pref |= PRE_67;
break;
default:
goto pref_done;
}
pref_done:
hs->flags = (uint32_t)pref << 23;
if (!pref)
pref |= PRE_NONE;
if ((c & 0xf0) == 0x40) {
hs->flags |= F_PREFIX_REX;
if ((hs->rex_w = (c & 0xf) >> 3) && (*p & 0xf8) == 0xb8)
op64++;
hs->rex_r = (c & 7) >> 2;
hs->rex_x = (c & 3) >> 1;
hs->rex_b = c & 1;
if (((c = *p++) & 0xf0) == 0x40) {
opcode = c;
goto error_opcode;
}
}
if ((hs->opcode = c) == 0x0f) {
hs->opcode2 = c = *p++;
ht += DELTA_OPCODES;
} else if (c >= 0xa0 && c <= 0xa3) {
op64++;
if (pref & PRE_67)
pref |= PRE_66;
else
pref &= ~PRE_66;
}
opcode = c;
cflags = ht[ht[opcode / 4] + (opcode % 4)];
if (cflags == C_ERROR) {
error_opcode:
hs->flags |= F_ERROR | F_ERROR_OPCODE;
cflags = 0;
if ((opcode & -3) == 0x24)
cflags++;
}
x = 0;
if (cflags & C_GROUP) {
uint16_t t;
t = *(uint16_t *)(ht + (cflags & 0x7f));
cflags = (uint8_t)t;
x = (uint8_t)(t >> 8);
}
if (hs->opcode2) {
ht = hde64_table + DELTA_PREFIXES;
if (ht[ht[opcode / 4] + (opcode % 4)] & pref)
hs->flags |= F_ERROR | F_ERROR_OPCODE;
}
if (cflags & C_MODRM) {
hs->flags |= F_MODRM;
hs->modrm = c = *p++;
hs->modrm_mod = m_mod = c >> 6;
hs->modrm_rm = m_rm = c & 7;
hs->modrm_reg = m_reg = (c & 0x3f) >> 3;
if (x && ((x << m_reg) & 0x80))
hs->flags |= F_ERROR | F_ERROR_OPCODE;
if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) {
uint8_t t = opcode - 0xd9;
if (m_mod == 3) {
ht = hde64_table + DELTA_FPU_MODRM + t*8;
t = ht[m_reg] << m_rm;
} else {
ht = hde64_table + DELTA_FPU_REG;
t = ht[t] << m_reg;
}
if (t & 0x80)
hs->flags |= F_ERROR | F_ERROR_OPCODE;
}
if (pref & PRE_LOCK) {
if (m_mod == 3) {
hs->flags |= F_ERROR | F_ERROR_LOCK;
} else {
uint8_t *table_end, op = opcode;
if (hs->opcode2) {
ht = hde64_table + DELTA_OP2_LOCK_OK;
table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK;
} else {
ht = hde64_table + DELTA_OP_LOCK_OK;
table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK;
op &= -2;
}
for (; ht != table_end; ht++)
if (*ht++ == op) {
if (!((*ht << m_reg) & 0x80))
goto no_lock_error;
else
break;
}
hs->flags |= F_ERROR | F_ERROR_LOCK;
no_lock_error:
;
}
}
if (hs->opcode2) {
switch (opcode) {
case 0x20: case 0x22:
m_mod = 3;
if (m_reg > 4 || m_reg == 1)
goto error_operand;
else
goto no_error_operand;
case 0x21: case 0x23:
m_mod = 3;
if (m_reg == 4 || m_reg == 5)
goto error_operand;
else
goto no_error_operand;
}
} else {
switch (opcode) {
case 0x8c:
if (m_reg > 5)
goto error_operand;
else
goto no_error_operand;
case 0x8e:
if (m_reg == 1 || m_reg > 5)
goto error_operand;
else
goto no_error_operand;
}
}
if (m_mod == 3) {
uint8_t *table_end;
if (hs->opcode2) {
ht = hde64_table + DELTA_OP2_ONLY_MEM;
table_end = ht + sizeof(hde64_table) - DELTA_OP2_ONLY_MEM;
} else {
ht = hde64_table + DELTA_OP_ONLY_MEM;
table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM;
}
for (; ht != table_end; ht += 2)
if (*ht++ == opcode) {
if (*ht++ & pref && !((*ht << m_reg) & 0x80))
goto error_operand;
else
break;
}
goto no_error_operand;
} else if (hs->opcode2) {
switch (opcode) {
case 0x50: case 0xd7: case 0xf7:
if (pref & (PRE_NONE | PRE_66))
goto error_operand;
break;
case 0xd6:
if (pref & (PRE_F2 | PRE_F3))
goto error_operand;
break;
case 0xc5:
goto error_operand;
}
goto no_error_operand;
} else
goto no_error_operand;
error_operand:
hs->flags |= F_ERROR | F_ERROR_OPERAND;
no_error_operand:
c = *p++;
if (m_reg <= 1) {
if (opcode == 0xf6)
cflags |= C_IMM8;
else if (opcode == 0xf7)
cflags |= C_IMM_P66;
}
switch (m_mod) {
case 0:
if (pref & PRE_67) {
if (m_rm == 6)
disp_size = 2;
} else
if (m_rm == 5)
disp_size = 4;
break;
case 1:
disp_size = 1;
break;
case 2:
disp_size = 2;
if (!(pref & PRE_67))
disp_size <<= 1;
}
if (m_mod != 3 && m_rm == 4) {
hs->flags |= F_SIB;
p++;
hs->sib = c;
hs->sib_scale = c >> 6;
hs->sib_index = (c & 0x3f) >> 3;
if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1))
disp_size = 4;
}
p--;
switch (disp_size) {
case 1:
hs->flags |= F_DISP8;
hs->disp.disp8 = *p;
break;
case 2:
hs->flags |= F_DISP16;
hs->disp.disp16 = *(uint16_t *)p;
break;
case 4:
hs->flags |= F_DISP32;
hs->disp.disp32 = *(uint32_t *)p;
}
p += disp_size;
} else if (pref & PRE_LOCK)
hs->flags |= F_ERROR | F_ERROR_LOCK;
if (cflags & C_IMM_P66) {
if (cflags & C_REL32) {
if (pref & PRE_66) {
hs->flags |= F_IMM16 | F_RELATIVE;
hs->imm.imm16 = *(uint16_t *)p;
p += 2;
goto disasm_done;
}
goto rel32_ok;
}
if (op64) {
hs->flags |= F_IMM64;
hs->imm.imm64 = *(uint64_t *)p;
p += 8;
} else if (!(pref & PRE_66)) {
hs->flags |= F_IMM32;
hs->imm.imm32 = *(uint32_t *)p;
p += 4;
} else
goto imm16_ok;
}
if (cflags & C_IMM16) {
imm16_ok:
hs->flags |= F_IMM16;
hs->imm.imm16 = *(uint16_t *)p;
p += 2;
}
if (cflags & C_IMM8) {
hs->flags |= F_IMM8;
hs->imm.imm8 = *p++;
}
if (cflags & C_REL32) {
rel32_ok:
hs->flags |= F_IMM32 | F_RELATIVE;
hs->imm.imm32 = *(uint32_t *)p;
p += 4;
} else if (cflags & C_REL8) {
hs->flags |= F_IMM8 | F_RELATIVE;
hs->imm.imm8 = *p++;
}
disasm_done:
if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) {
hs->flags |= F_ERROR | F_ERROR_LENGTH;
hs->len = 15;
}
return (unsigned int)hs->len;
}
#endif // defined(_M_X64) || defined(__x86_64__)

View File

@@ -0,0 +1,112 @@
/*
* Hacker Disassembler Engine 64
* Copyright (c) 2008-2009, Vyacheslav Patkov.
* All rights reserved.
*
* hde64.h: C/C++ header file
*
*/
#ifndef _HDE64_H_
#define _HDE64_H_
/* stdint.h - C99 standard header
* http://en.wikipedia.org/wiki/stdint.h
*
* if your compiler doesn't contain "stdint.h" header (for
* example, Microsoft Visual C++), you can download file:
* http://www.azillionmonkeys.com/qed/pstdint.h
* and change next line to:
* #include "pstdint.h"
*/
#include "pstdint.h"
#define F_MODRM 0x00000001
#define F_SIB 0x00000002
#define F_IMM8 0x00000004
#define F_IMM16 0x00000008
#define F_IMM32 0x00000010
#define F_IMM64 0x00000020
#define F_DISP8 0x00000040
#define F_DISP16 0x00000080
#define F_DISP32 0x00000100
#define F_RELATIVE 0x00000200
#define F_ERROR 0x00001000
#define F_ERROR_OPCODE 0x00002000
#define F_ERROR_LENGTH 0x00004000
#define F_ERROR_LOCK 0x00008000
#define F_ERROR_OPERAND 0x00010000
#define F_PREFIX_REPNZ 0x01000000
#define F_PREFIX_REPX 0x02000000
#define F_PREFIX_REP 0x03000000
#define F_PREFIX_66 0x04000000
#define F_PREFIX_67 0x08000000
#define F_PREFIX_LOCK 0x10000000
#define F_PREFIX_SEG 0x20000000
#define F_PREFIX_REX 0x40000000
#define F_PREFIX_ANY 0x7f000000
#define PREFIX_SEGMENT_CS 0x2e
#define PREFIX_SEGMENT_SS 0x36
#define PREFIX_SEGMENT_DS 0x3e
#define PREFIX_SEGMENT_ES 0x26
#define PREFIX_SEGMENT_FS 0x64
#define PREFIX_SEGMENT_GS 0x65
#define PREFIX_LOCK 0xf0
#define PREFIX_REPNZ 0xf2
#define PREFIX_REPX 0xf3
#define PREFIX_OPERAND_SIZE 0x66
#define PREFIX_ADDRESS_SIZE 0x67
#pragma pack(push,1)
typedef struct {
uint8_t len;
uint8_t p_rep;
uint8_t p_lock;
uint8_t p_seg;
uint8_t p_66;
uint8_t p_67;
uint8_t rex;
uint8_t rex_w;
uint8_t rex_r;
uint8_t rex_x;
uint8_t rex_b;
uint8_t opcode;
uint8_t opcode2;
uint8_t modrm;
uint8_t modrm_mod;
uint8_t modrm_reg;
uint8_t modrm_rm;
uint8_t sib;
uint8_t sib_scale;
uint8_t sib_index;
uint8_t sib_base;
union {
uint8_t imm8;
uint16_t imm16;
uint32_t imm32;
uint64_t imm64;
} imm;
union {
uint8_t disp8;
uint16_t disp16;
uint32_t disp32;
} disp;
uint32_t flags;
} hde64s;
#pragma pack(pop)
#ifdef __cplusplus
extern "C" {
#endif
/* __cdecl */
unsigned int hde64_disasm(const void *code, hde64s *hs);
#ifdef __cplusplus
}
#endif
#endif /* _HDE64_H_ */

View File

@@ -0,0 +1,39 @@
/*
* MinHook - The Minimalistic API Hooking Library for x64/x86
* Copyright (C) 2009-2017 Tsuda Kageyu. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <windows.h>
// Integer types for HDE.
typedef INT8 int8_t;
typedef INT16 int16_t;
typedef INT32 int32_t;
typedef INT64 int64_t;
typedef UINT8 uint8_t;
typedef UINT16 uint16_t;
typedef UINT32 uint32_t;
typedef UINT64 uint64_t;

View File

@@ -0,0 +1,73 @@
/*
* Hacker Disassembler Engine 32 C
* Copyright (c) 2008-2009, Vyacheslav Patkov.
* All rights reserved.
*
*/
#define C_NONE 0x00
#define C_MODRM 0x01
#define C_IMM8 0x02
#define C_IMM16 0x04
#define C_IMM_P66 0x10
#define C_REL8 0x20
#define C_REL32 0x40
#define C_GROUP 0x80
#define C_ERROR 0xff
#define PRE_ANY 0x00
#define PRE_NONE 0x01
#define PRE_F2 0x02
#define PRE_F3 0x04
#define PRE_66 0x08
#define PRE_67 0x10
#define PRE_LOCK 0x20
#define PRE_SEG 0x40
#define PRE_ALL 0xff
#define DELTA_OPCODES 0x4a
#define DELTA_FPU_REG 0xf1
#define DELTA_FPU_MODRM 0xf8
#define DELTA_PREFIXES 0x130
#define DELTA_OP_LOCK_OK 0x1a1
#define DELTA_OP2_LOCK_OK 0x1b9
#define DELTA_OP_ONLY_MEM 0x1cb
#define DELTA_OP2_ONLY_MEM 0x1da
unsigned char hde32_table[] = {
0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,
0xa8,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xac,0xaa,0xb2,0xaa,0x9f,0x9f,
0x9f,0x9f,0xb5,0xa3,0xa3,0xa4,0xaa,0xaa,0xba,0xaa,0x96,0xaa,0xa8,0xaa,0xc3,
0xc3,0x96,0x96,0xb7,0xae,0xd6,0xbd,0xa3,0xc5,0xa3,0xa3,0x9f,0xc3,0x9c,0xaa,
0xaa,0xac,0xaa,0xbf,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0x90,
0x82,0x7d,0x97,0x59,0x59,0x59,0x59,0x59,0x7f,0x59,0x59,0x60,0x7d,0x7f,0x7f,
0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x9a,0x88,0x7d,
0x59,0x50,0x50,0x50,0x50,0x59,0x59,0x59,0x59,0x61,0x94,0x61,0x9e,0x59,0x59,
0x85,0x59,0x92,0xa3,0x60,0x60,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,
0x59,0x59,0x9f,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xcc,0x01,0xbc,0x03,0xf0,
0x10,0x10,0x10,0x10,0x50,0x50,0x50,0x50,0x14,0x20,0x20,0x20,0x20,0x01,0x01,
0x01,0x01,0xc4,0x02,0x10,0x00,0x00,0x00,0x00,0x01,0x01,0xc0,0xc2,0x10,0x11,
0x02,0x03,0x11,0x03,0x03,0x04,0x00,0x00,0x14,0x00,0x02,0x00,0x00,0xc6,0xc8,
0x02,0x02,0x02,0x02,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0xca,
0x01,0x01,0x01,0x00,0x06,0x00,0x04,0x00,0xc0,0xc2,0x01,0x01,0x03,0x01,0xff,
0xff,0x01,0x00,0x03,0xc4,0xc4,0xc6,0x03,0x01,0x01,0x01,0xff,0x03,0x03,0x03,
0xc8,0x40,0x00,0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,
0x00,0x00,0x00,0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,
0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0xff,0xff,0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x7f,0x00,0x00,0xff,0x4a,0x4a,0x4a,0x4a,0x4b,0x52,0x4a,0x4a,0x4a,0x4a,0x4f,
0x4c,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x55,0x45,0x40,0x4a,0x4a,0x4a,
0x45,0x59,0x4d,0x46,0x4a,0x5d,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,
0x4a,0x4a,0x4a,0x4a,0x4a,0x61,0x63,0x67,0x4e,0x4a,0x4a,0x6b,0x6d,0x4a,0x4a,
0x45,0x6d,0x4a,0x4a,0x44,0x45,0x4a,0x4a,0x00,0x00,0x00,0x02,0x0d,0x06,0x06,
0x06,0x06,0x0e,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x00,0x06,0x06,0x02,0x06,
0x00,0x0a,0x0a,0x07,0x07,0x06,0x02,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04,
0x04,0x04,0x00,0x00,0x00,0x0e,0x05,0x06,0x06,0x06,0x01,0x06,0x00,0x00,0x08,
0x00,0x10,0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,
0x86,0x00,0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,
0xf8,0xbb,0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,
0xc4,0xff,0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,
0x13,0x09,0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,
0xb2,0xff,0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,
0xe7,0x08,0x00,0xf0,0x02,0x00
};

View File

@@ -0,0 +1,74 @@
/*
* Hacker Disassembler Engine 64 C
* Copyright (c) 2008-2009, Vyacheslav Patkov.
* All rights reserved.
*
*/
#define C_NONE 0x00
#define C_MODRM 0x01
#define C_IMM8 0x02
#define C_IMM16 0x04
#define C_IMM_P66 0x10
#define C_REL8 0x20
#define C_REL32 0x40
#define C_GROUP 0x80
#define C_ERROR 0xff
#define PRE_ANY 0x00
#define PRE_NONE 0x01
#define PRE_F2 0x02
#define PRE_F3 0x04
#define PRE_66 0x08
#define PRE_67 0x10
#define PRE_LOCK 0x20
#define PRE_SEG 0x40
#define PRE_ALL 0xff
#define DELTA_OPCODES 0x4a
#define DELTA_FPU_REG 0xfd
#define DELTA_FPU_MODRM 0x104
#define DELTA_PREFIXES 0x13c
#define DELTA_OP_LOCK_OK 0x1ae
#define DELTA_OP2_LOCK_OK 0x1c6
#define DELTA_OP_ONLY_MEM 0x1d8
#define DELTA_OP2_ONLY_MEM 0x1e7
unsigned char hde64_table[] = {
0xa5,0xaa,0xa5,0xb8,0xa5,0xaa,0xa5,0xaa,0xa5,0xb8,0xa5,0xb8,0xa5,0xb8,0xa5,
0xb8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xac,0xc0,0xcc,0xc0,0xa1,0xa1,
0xa1,0xa1,0xb1,0xa5,0xa5,0xa6,0xc0,0xc0,0xd7,0xda,0xe0,0xc0,0xe4,0xc0,0xea,
0xea,0xe0,0xe0,0x98,0xc8,0xee,0xf1,0xa5,0xd3,0xa5,0xa5,0xa1,0xea,0x9e,0xc0,
0xc0,0xc2,0xc0,0xe6,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0xab,
0x8b,0x90,0x64,0x5b,0x5b,0x5b,0x5b,0x5b,0x92,0x5b,0x5b,0x76,0x90,0x92,0x92,
0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x6a,0x73,0x90,
0x5b,0x52,0x52,0x52,0x52,0x5b,0x5b,0x5b,0x5b,0x77,0x7c,0x77,0x85,0x5b,0x5b,
0x70,0x5b,0x7a,0xaf,0x76,0x76,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,
0x5b,0x5b,0x86,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xd5,0x03,0xcc,0x01,0xbc,
0x03,0xf0,0x03,0x03,0x04,0x00,0x50,0x50,0x50,0x50,0xff,0x20,0x20,0x20,0x20,
0x01,0x01,0x01,0x01,0xc4,0x02,0x10,0xff,0xff,0xff,0x01,0x00,0x03,0x11,0xff,
0x03,0xc4,0xc6,0xc8,0x02,0x10,0x00,0xff,0xcc,0x01,0x01,0x01,0x00,0x00,0x00,
0x00,0x01,0x01,0x03,0x01,0xff,0xff,0xc0,0xc2,0x10,0x11,0x02,0x03,0x01,0x01,
0x01,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x10,
0x10,0x10,0x10,0x02,0x10,0x00,0x00,0xc6,0xc8,0x02,0x02,0x02,0x02,0x06,0x00,
0x04,0x00,0x02,0xff,0x00,0xc0,0xc2,0x01,0x01,0x03,0x03,0x03,0xca,0x40,0x00,
0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,0x00,0x00,0x00,
0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xff,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,
0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00,
0xff,0x40,0x40,0x40,0x40,0x41,0x49,0x40,0x40,0x40,0x40,0x4c,0x42,0x40,0x40,
0x40,0x40,0x40,0x40,0x40,0x40,0x4f,0x44,0x53,0x40,0x40,0x40,0x44,0x57,0x43,
0x5c,0x40,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
0x40,0x40,0x64,0x66,0x6e,0x6b,0x40,0x40,0x6a,0x46,0x40,0x40,0x44,0x46,0x40,
0x40,0x5b,0x44,0x40,0x40,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x01,0x06,
0x06,0x02,0x06,0x06,0x00,0x06,0x00,0x0a,0x0a,0x00,0x00,0x00,0x02,0x07,0x07,
0x06,0x02,0x0d,0x06,0x06,0x06,0x0e,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04,
0x04,0x04,0x05,0x06,0x06,0x06,0x00,0x00,0x00,0x0e,0x00,0x00,0x08,0x00,0x10,
0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,0x86,0x00,
0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,0xf8,0xbb,
0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,0xc4,0xff,
0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,0x13,0x09,
0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,0xb2,0xff,
0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,0xe7,0x08,
0x00,0xf0,0x02,0x00
};

View File

@@ -0,0 +1,312 @@
/*
* MinHook - The Minimalistic API Hooking Library for x64/x86
* Copyright (C) 2009-2017 Tsuda Kageyu.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <windows.h>
#include "buffer.h"
// Size of each memory block. (= page size of VirtualAlloc)
#define MEMORY_BLOCK_SIZE 0x1000
// Max range for seeking a memory block. (= 1024MB)
#define MAX_MEMORY_RANGE 0x40000000
// Memory protection flags to check the executable address.
#define PAGE_EXECUTE_FLAGS \
(PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)
// Memory slot.
typedef struct _MEMORY_SLOT
{
union
{
struct _MEMORY_SLOT *pNext;
UINT8 buffer[MEMORY_SLOT_SIZE];
};
} MEMORY_SLOT, *PMEMORY_SLOT;
// Memory block info. Placed at the head of each block.
typedef struct _MEMORY_BLOCK
{
struct _MEMORY_BLOCK *pNext;
PMEMORY_SLOT pFree; // First element of the free slot list.
UINT usedCount;
} MEMORY_BLOCK, *PMEMORY_BLOCK;
//-------------------------------------------------------------------------
// Global Variables:
//-------------------------------------------------------------------------
// First element of the memory block list.
PMEMORY_BLOCK g_pMemoryBlocks;
//-------------------------------------------------------------------------
VOID InitializeBuffer(VOID)
{
// Nothing to do for now.
}
//-------------------------------------------------------------------------
VOID UninitializeBuffer(VOID)
{
PMEMORY_BLOCK pBlock = g_pMemoryBlocks;
g_pMemoryBlocks = NULL;
while (pBlock)
{
PMEMORY_BLOCK pNext = pBlock->pNext;
VirtualFree(pBlock, 0, MEM_RELEASE);
pBlock = pNext;
}
}
//-------------------------------------------------------------------------
#if defined(_M_X64) || defined(__x86_64__)
static LPVOID FindPrevFreeRegion(LPVOID pAddress, LPVOID pMinAddr, DWORD dwAllocationGranularity)
{
ULONG_PTR tryAddr = (ULONG_PTR)pAddress;
// Round down to the allocation granularity.
tryAddr -= tryAddr % dwAllocationGranularity;
// Start from the previous allocation granularity multiply.
tryAddr -= dwAllocationGranularity;
while (tryAddr >= (ULONG_PTR)pMinAddr)
{
MEMORY_BASIC_INFORMATION mbi;
if (VirtualQuery((LPVOID)tryAddr, &mbi, sizeof(mbi)) == 0)
break;
if (mbi.State == MEM_FREE)
return (LPVOID)tryAddr;
if ((ULONG_PTR)mbi.AllocationBase < dwAllocationGranularity)
break;
tryAddr = (ULONG_PTR)mbi.AllocationBase - dwAllocationGranularity;
}
return NULL;
}
#endif
//-------------------------------------------------------------------------
#if defined(_M_X64) || defined(__x86_64__)
static LPVOID FindNextFreeRegion(LPVOID pAddress, LPVOID pMaxAddr, DWORD dwAllocationGranularity)
{
ULONG_PTR tryAddr = (ULONG_PTR)pAddress;
// Round down to the allocation granularity.
tryAddr -= tryAddr % dwAllocationGranularity;
// Start from the next allocation granularity multiply.
tryAddr += dwAllocationGranularity;
while (tryAddr <= (ULONG_PTR)pMaxAddr)
{
MEMORY_BASIC_INFORMATION mbi;
if (VirtualQuery((LPVOID)tryAddr, &mbi, sizeof(mbi)) == 0)
break;
if (mbi.State == MEM_FREE)
return (LPVOID)tryAddr;
tryAddr = (ULONG_PTR)mbi.BaseAddress + mbi.RegionSize;
// Round up to the next allocation granularity.
tryAddr += dwAllocationGranularity - 1;
tryAddr -= tryAddr % dwAllocationGranularity;
}
return NULL;
}
#endif
//-------------------------------------------------------------------------
static PMEMORY_BLOCK GetMemoryBlock(LPVOID pOrigin)
{
PMEMORY_BLOCK pBlock;
#if defined(_M_X64) || defined(__x86_64__)
ULONG_PTR minAddr;
ULONG_PTR maxAddr;
SYSTEM_INFO si;
GetSystemInfo(&si);
minAddr = (ULONG_PTR)si.lpMinimumApplicationAddress;
maxAddr = (ULONG_PTR)si.lpMaximumApplicationAddress;
// pOrigin ± 512MB
if ((ULONG_PTR)pOrigin > MAX_MEMORY_RANGE && minAddr < (ULONG_PTR)pOrigin - MAX_MEMORY_RANGE)
minAddr = (ULONG_PTR)pOrigin - MAX_MEMORY_RANGE;
if (maxAddr > (ULONG_PTR)pOrigin + MAX_MEMORY_RANGE)
maxAddr = (ULONG_PTR)pOrigin + MAX_MEMORY_RANGE;
// Make room for MEMORY_BLOCK_SIZE bytes.
maxAddr -= MEMORY_BLOCK_SIZE - 1;
#endif
// Look the registered blocks for a reachable one.
for (pBlock = g_pMemoryBlocks; pBlock != NULL; pBlock = pBlock->pNext)
{
#if defined(_M_X64) || defined(__x86_64__)
// Ignore the blocks too far.
if ((ULONG_PTR)pBlock < minAddr || (ULONG_PTR)pBlock >= maxAddr)
continue;
#endif
// The block has at least one unused slot.
if (pBlock->pFree != NULL)
return pBlock;
}
#if defined(_M_X64) || defined(__x86_64__)
// Alloc a new block above if not found.
{
LPVOID pAlloc = pOrigin;
while ((ULONG_PTR)pAlloc >= minAddr)
{
pAlloc = FindPrevFreeRegion(pAlloc, (LPVOID)minAddr, si.dwAllocationGranularity);
if (pAlloc == NULL)
break;
pBlock = (PMEMORY_BLOCK)VirtualAlloc(
pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (pBlock != NULL)
break;
}
}
// Alloc a new block below if not found.
if (pBlock == NULL)
{
LPVOID pAlloc = pOrigin;
while ((ULONG_PTR)pAlloc <= maxAddr)
{
pAlloc = FindNextFreeRegion(pAlloc, (LPVOID)maxAddr, si.dwAllocationGranularity);
if (pAlloc == NULL)
break;
pBlock = (PMEMORY_BLOCK)VirtualAlloc(
pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (pBlock != NULL)
break;
}
}
#else
// In x86 mode, a memory block can be placed anywhere.
pBlock = (PMEMORY_BLOCK)VirtualAlloc(
NULL, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
#endif
if (pBlock != NULL)
{
// Build a linked list of all the slots.
PMEMORY_SLOT pSlot = (PMEMORY_SLOT)pBlock + 1;
pBlock->pFree = NULL;
pBlock->usedCount = 0;
do
{
pSlot->pNext = pBlock->pFree;
pBlock->pFree = pSlot;
pSlot++;
} while ((ULONG_PTR)pSlot - (ULONG_PTR)pBlock <= MEMORY_BLOCK_SIZE - MEMORY_SLOT_SIZE);
pBlock->pNext = g_pMemoryBlocks;
g_pMemoryBlocks = pBlock;
}
return pBlock;
}
//-------------------------------------------------------------------------
LPVOID AllocateBuffer(LPVOID pOrigin)
{
PMEMORY_SLOT pSlot;
PMEMORY_BLOCK pBlock = GetMemoryBlock(pOrigin);
if (pBlock == NULL)
return NULL;
// Remove an unused slot from the list.
pSlot = pBlock->pFree;
pBlock->pFree = pSlot->pNext;
pBlock->usedCount++;
#ifdef _DEBUG
// Fill the slot with INT3 for debugging.
memset(pSlot, 0xCC, sizeof(MEMORY_SLOT));
#endif
return pSlot;
}
//-------------------------------------------------------------------------
VOID FreeBuffer(LPVOID pBuffer)
{
PMEMORY_BLOCK pBlock = g_pMemoryBlocks;
PMEMORY_BLOCK pPrev = NULL;
ULONG_PTR pTargetBlock = ((ULONG_PTR)pBuffer / MEMORY_BLOCK_SIZE) * MEMORY_BLOCK_SIZE;
while (pBlock != NULL)
{
if ((ULONG_PTR)pBlock == pTargetBlock)
{
PMEMORY_SLOT pSlot = (PMEMORY_SLOT)pBuffer;
#ifdef _DEBUG
// Clear the released slot for debugging.
memset(pSlot, 0x00, sizeof(MEMORY_SLOT));
#endif
// Restore the released slot to the list.
pSlot->pNext = pBlock->pFree;
pBlock->pFree = pSlot;
pBlock->usedCount--;
// Free if unused.
if (pBlock->usedCount == 0)
{
if (pPrev)
pPrev->pNext = pBlock->pNext;
else
g_pMemoryBlocks = pBlock->pNext;
VirtualFree(pBlock, 0, MEM_RELEASE);
}
break;
}
pPrev = pBlock;
pBlock = pBlock->pNext;
}
}
//-------------------------------------------------------------------------
BOOL IsExecutableAddress(LPVOID pAddress)
{
MEMORY_BASIC_INFORMATION mi;
VirtualQuery(pAddress, &mi, sizeof(mi));
return (mi.State == MEM_COMMIT && (mi.Protect & PAGE_EXECUTE_FLAGS));
}

View File

@@ -0,0 +1,42 @@
/*
* MinHook - The Minimalistic API Hooking Library for x64/x86
* Copyright (C) 2009-2017 Tsuda Kageyu.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
// Size of each memory slot.
#if defined(_M_X64) || defined(__x86_64__)
#define MEMORY_SLOT_SIZE 64
#else
#define MEMORY_SLOT_SIZE 32
#endif
VOID InitializeBuffer(VOID);
VOID UninitializeBuffer(VOID);
LPVOID AllocateBuffer(LPVOID pOrigin);
VOID FreeBuffer(LPVOID pBuffer);
BOOL IsExecutableAddress(LPVOID pAddress);

View File

@@ -0,0 +1,889 @@
/*
* MinHook - The Minimalistic API Hooking Library for x64/x86
* Copyright (C) 2009-2017 Tsuda Kageyu.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <windows.h>
#include <tlhelp32.h>
#include <limits.h>
#include "../include/MinHook.h"
#include "buffer.h"
#include "trampoline.h"
#ifndef ARRAYSIZE
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif
// Initial capacity of the HOOK_ENTRY buffer.
#define INITIAL_HOOK_CAPACITY 32
// Initial capacity of the thread IDs buffer.
#define INITIAL_THREAD_CAPACITY 128
// Special hook position values.
#define INVALID_HOOK_POS UINT_MAX
#define ALL_HOOKS_POS UINT_MAX
// Freeze() action argument defines.
#define ACTION_DISABLE 0
#define ACTION_ENABLE 1
#define ACTION_APPLY_QUEUED 2
// Thread access rights for suspending/resuming threads.
#define THREAD_ACCESS \
(THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION | THREAD_SET_CONTEXT)
// Hook information.
typedef struct _HOOK_ENTRY
{
LPVOID pTarget; // Address of the target function.
LPVOID pDetour; // Address of the detour or relay function.
LPVOID pTrampoline; // Address of the trampoline function.
UINT8 backup[8]; // Original prologue of the target function.
UINT8 patchAbove : 1; // Uses the hot patch area.
UINT8 isEnabled : 1; // Enabled.
UINT8 queueEnable : 1; // Queued for enabling/disabling when != isEnabled.
UINT nIP : 4; // Count of the instruction boundaries.
UINT8 oldIPs[8]; // Instruction boundaries of the target function.
UINT8 newIPs[8]; // Instruction boundaries of the trampoline function.
} HOOK_ENTRY, *PHOOK_ENTRY;
// Suspended threads for Freeze()/Unfreeze().
typedef struct _FROZEN_THREADS
{
LPDWORD pItems; // Data heap
UINT capacity; // Size of allocated data heap, items
UINT size; // Actual number of data items
} FROZEN_THREADS, *PFROZEN_THREADS;
//-------------------------------------------------------------------------
// Global Variables:
//-------------------------------------------------------------------------
// Spin lock flag for EnterSpinLock()/LeaveSpinLock().
volatile LONG g_isLocked = FALSE;
// Private heap handle. If not NULL, this library is initialized.
HANDLE g_hHeap = NULL;
// Hook entries.
struct
{
PHOOK_ENTRY pItems; // Data heap
UINT capacity; // Size of allocated data heap, items
UINT size; // Actual number of data items
} g_hooks;
//-------------------------------------------------------------------------
// Returns INVALID_HOOK_POS if not found.
static UINT FindHookEntry(LPVOID pTarget)
{
UINT i;
for (i = 0; i < g_hooks.size; ++i)
{
if ((ULONG_PTR)pTarget == (ULONG_PTR)g_hooks.pItems[i].pTarget)
return i;
}
return INVALID_HOOK_POS;
}
//-------------------------------------------------------------------------
static PHOOK_ENTRY AddHookEntry()
{
if (g_hooks.pItems == NULL)
{
g_hooks.capacity = INITIAL_HOOK_CAPACITY;
g_hooks.pItems = (PHOOK_ENTRY)HeapAlloc(
g_hHeap, 0, g_hooks.capacity * sizeof(HOOK_ENTRY));
if (g_hooks.pItems == NULL)
return NULL;
}
else if (g_hooks.size >= g_hooks.capacity)
{
PHOOK_ENTRY p = (PHOOK_ENTRY)HeapReAlloc(
g_hHeap, 0, g_hooks.pItems, (g_hooks.capacity * 2) * sizeof(HOOK_ENTRY));
if (p == NULL)
return NULL;
g_hooks.capacity *= 2;
g_hooks.pItems = p;
}
return &g_hooks.pItems[g_hooks.size++];
}
//-------------------------------------------------------------------------
static void DeleteHookEntry(UINT pos)
{
if (pos < g_hooks.size - 1)
g_hooks.pItems[pos] = g_hooks.pItems[g_hooks.size - 1];
g_hooks.size--;
if (g_hooks.capacity / 2 >= INITIAL_HOOK_CAPACITY && g_hooks.capacity / 2 >= g_hooks.size)
{
PHOOK_ENTRY p = (PHOOK_ENTRY)HeapReAlloc(
g_hHeap, 0, g_hooks.pItems, (g_hooks.capacity / 2) * sizeof(HOOK_ENTRY));
if (p == NULL)
return;
g_hooks.capacity /= 2;
g_hooks.pItems = p;
}
}
//-------------------------------------------------------------------------
static DWORD_PTR FindOldIP(PHOOK_ENTRY pHook, DWORD_PTR ip)
{
UINT i;
if (pHook->patchAbove && ip == ((DWORD_PTR)pHook->pTarget - sizeof(JMP_REL)))
return (DWORD_PTR)pHook->pTarget;
for (i = 0; i < pHook->nIP; ++i)
{
if (ip == ((DWORD_PTR)pHook->pTrampoline + pHook->newIPs[i]))
return (DWORD_PTR)pHook->pTarget + pHook->oldIPs[i];
}
#if defined(_M_X64) || defined(__x86_64__)
// Check relay function.
if (ip == (DWORD_PTR)pHook->pDetour)
return (DWORD_PTR)pHook->pTarget;
#endif
return 0;
}
//-------------------------------------------------------------------------
static DWORD_PTR FindNewIP(PHOOK_ENTRY pHook, DWORD_PTR ip)
{
UINT i;
for (i = 0; i < pHook->nIP; ++i)
{
if (ip == ((DWORD_PTR)pHook->pTarget + pHook->oldIPs[i]))
return (DWORD_PTR)pHook->pTrampoline + pHook->newIPs[i];
}
return 0;
}
//-------------------------------------------------------------------------
static void ProcessThreadIPs(HANDLE hThread, UINT pos, UINT action)
{
// If the thread suspended in the overwritten area,
// move IP to the proper address.
CONTEXT c;
#if defined(_M_X64) || defined(__x86_64__)
DWORD64 *pIP = &c.Rip;
#else
DWORD *pIP = &c.Eip;
#endif
UINT count;
c.ContextFlags = CONTEXT_CONTROL;
if (!GetThreadContext(hThread, &c))
return;
if (pos == ALL_HOOKS_POS)
{
pos = 0;
count = g_hooks.size;
}
else
{
count = pos + 1;
}
for (; pos < count; ++pos)
{
PHOOK_ENTRY pHook = &g_hooks.pItems[pos];
BOOL enable;
DWORD_PTR ip;
switch (action)
{
case ACTION_DISABLE:
enable = FALSE;
break;
case ACTION_ENABLE:
enable = TRUE;
break;
default: // ACTION_APPLY_QUEUED
enable = pHook->queueEnable;
break;
}
if (pHook->isEnabled == enable)
continue;
if (enable)
ip = FindNewIP(pHook, *pIP);
else
ip = FindOldIP(pHook, *pIP);
if (ip != 0)
{
*pIP = ip;
SetThreadContext(hThread, &c);
}
}
}
//-------------------------------------------------------------------------
static VOID EnumerateThreads(PFROZEN_THREADS pThreads)
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hSnapshot != INVALID_HANDLE_VALUE)
{
THREADENTRY32 te;
te.dwSize = sizeof(THREADENTRY32);
if (Thread32First(hSnapshot, &te))
{
do
{
if (te.dwSize >= (FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(DWORD))
&& te.th32OwnerProcessID == GetCurrentProcessId()
&& te.th32ThreadID != GetCurrentThreadId())
{
if (pThreads->pItems == NULL)
{
pThreads->capacity = INITIAL_THREAD_CAPACITY;
pThreads->pItems
= (LPDWORD)HeapAlloc(g_hHeap, 0, pThreads->capacity * sizeof(DWORD));
if (pThreads->pItems == NULL)
break;
}
else if (pThreads->size >= pThreads->capacity)
{
LPDWORD p = (LPDWORD)HeapReAlloc(
g_hHeap, 0, pThreads->pItems, (pThreads->capacity * 2) * sizeof(DWORD));
if (p == NULL)
break;
pThreads->capacity *= 2;
pThreads->pItems = p;
}
pThreads->pItems[pThreads->size++] = te.th32ThreadID;
}
te.dwSize = sizeof(THREADENTRY32);
} while (Thread32Next(hSnapshot, &te));
}
CloseHandle(hSnapshot);
}
}
//-------------------------------------------------------------------------
static VOID Freeze(PFROZEN_THREADS pThreads, UINT pos, UINT action)
{
pThreads->pItems = NULL;
pThreads->capacity = 0;
pThreads->size = 0;
EnumerateThreads(pThreads);
if (pThreads->pItems != NULL)
{
UINT i;
for (i = 0; i < pThreads->size; ++i)
{
HANDLE hThread = OpenThread(THREAD_ACCESS, FALSE, pThreads->pItems[i]);
if (hThread != NULL)
{
SuspendThread(hThread);
ProcessThreadIPs(hThread, pos, action);
CloseHandle(hThread);
}
}
}
}
//-------------------------------------------------------------------------
static VOID Unfreeze(PFROZEN_THREADS pThreads)
{
if (pThreads->pItems != NULL)
{
UINT i;
for (i = 0; i < pThreads->size; ++i)
{
HANDLE hThread = OpenThread(THREAD_ACCESS, FALSE, pThreads->pItems[i]);
if (hThread != NULL)
{
ResumeThread(hThread);
CloseHandle(hThread);
}
}
HeapFree(g_hHeap, 0, pThreads->pItems);
}
}
//-------------------------------------------------------------------------
static MH_STATUS EnableHookLL(UINT pos, BOOL enable)
{
PHOOK_ENTRY pHook = &g_hooks.pItems[pos];
DWORD oldProtect;
SIZE_T patchSize = sizeof(JMP_REL);
LPBYTE pPatchTarget = (LPBYTE)pHook->pTarget;
if (pHook->patchAbove)
{
pPatchTarget -= sizeof(JMP_REL);
patchSize += sizeof(JMP_REL_SHORT);
}
if (!VirtualProtect(pPatchTarget, patchSize, PAGE_EXECUTE_READWRITE, &oldProtect))
return MH_ERROR_MEMORY_PROTECT;
if (enable)
{
PJMP_REL pJmp = (PJMP_REL)pPatchTarget;
pJmp->opcode = 0xE9;
pJmp->operand = (UINT32)((LPBYTE)pHook->pDetour - (pPatchTarget + sizeof(JMP_REL)));
if (pHook->patchAbove)
{
PJMP_REL_SHORT pShortJmp = (PJMP_REL_SHORT)pHook->pTarget;
pShortJmp->opcode = 0xEB;
pShortJmp->operand = (UINT8)(0 - (sizeof(JMP_REL_SHORT) + sizeof(JMP_REL)));
}
}
else
{
if (pHook->patchAbove)
memcpy(pPatchTarget, pHook->backup, sizeof(JMP_REL) + sizeof(JMP_REL_SHORT));
else
memcpy(pPatchTarget, pHook->backup, sizeof(JMP_REL));
}
VirtualProtect(pPatchTarget, patchSize, oldProtect, &oldProtect);
// Just-in-case measure.
FlushInstructionCache(GetCurrentProcess(), pPatchTarget, patchSize);
pHook->isEnabled = enable;
pHook->queueEnable = enable;
return MH_OK;
}
//-------------------------------------------------------------------------
static MH_STATUS EnableAllHooksLL(BOOL enable)
{
MH_STATUS status = MH_OK;
UINT i, first = INVALID_HOOK_POS;
for (i = 0; i < g_hooks.size; ++i)
{
if (g_hooks.pItems[i].isEnabled != enable)
{
first = i;
break;
}
}
if (first != INVALID_HOOK_POS)
{
FROZEN_THREADS threads;
Freeze(&threads, ALL_HOOKS_POS, enable ? ACTION_ENABLE : ACTION_DISABLE);
for (i = first; i < g_hooks.size; ++i)
{
if (g_hooks.pItems[i].isEnabled != enable)
{
status = EnableHookLL(i, enable);
if (status != MH_OK)
break;
}
}
Unfreeze(&threads);
}
return status;
}
//-------------------------------------------------------------------------
static VOID EnterSpinLock(VOID)
{
SIZE_T spinCount = 0;
// Wait until the flag is FALSE.
while (InterlockedCompareExchange(&g_isLocked, TRUE, FALSE) != FALSE)
{
// No need to generate a memory barrier here, since InterlockedCompareExchange()
// generates a full memory barrier itself.
// Prevent the loop from being too busy.
if (spinCount < 32)
Sleep(0);
else
Sleep(1);
spinCount++;
}
}
//-------------------------------------------------------------------------
static VOID LeaveSpinLock(VOID)
{
// No need to generate a memory barrier here, since InterlockedExchange()
// generates a full memory barrier itself.
InterlockedExchange(&g_isLocked, FALSE);
}
//-------------------------------------------------------------------------
MH_STATUS WINAPI MH_Initialize(VOID)
{
MH_STATUS status = MH_OK;
EnterSpinLock();
if (g_hHeap == NULL)
{
g_hHeap = HeapCreate(0, 0, 0);
if (g_hHeap != NULL)
{
// Initialize the internal function buffer.
InitializeBuffer();
}
else
{
status = MH_ERROR_MEMORY_ALLOC;
}
}
else
{
status = MH_ERROR_ALREADY_INITIALIZED;
}
LeaveSpinLock();
return status;
}
//-------------------------------------------------------------------------
MH_STATUS WINAPI MH_Uninitialize(VOID)
{
MH_STATUS status = MH_OK;
EnterSpinLock();
if (g_hHeap != NULL)
{
status = EnableAllHooksLL(FALSE);
if (status == MH_OK)
{
// Free the internal function buffer.
// HeapFree is actually not required, but some tools detect a false
// memory leak without HeapFree.
UninitializeBuffer();
HeapFree(g_hHeap, 0, g_hooks.pItems);
HeapDestroy(g_hHeap);
g_hHeap = NULL;
g_hooks.pItems = NULL;
g_hooks.capacity = 0;
g_hooks.size = 0;
}
}
else
{
status = MH_ERROR_NOT_INITIALIZED;
}
LeaveSpinLock();
return status;
}
//-------------------------------------------------------------------------
MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal)
{
MH_STATUS status = MH_OK;
EnterSpinLock();
if (g_hHeap != NULL)
{
if (IsExecutableAddress(pTarget) && IsExecutableAddress(pDetour))
{
UINT pos = FindHookEntry(pTarget);
if (pos == INVALID_HOOK_POS)
{
LPVOID pBuffer = AllocateBuffer(pTarget);
if (pBuffer != NULL)
{
TRAMPOLINE ct;
ct.pTarget = pTarget;
ct.pDetour = pDetour;
ct.pTrampoline = pBuffer;
if (CreateTrampolineFunction(&ct))
{
PHOOK_ENTRY pHook = AddHookEntry();
if (pHook != NULL)
{
pHook->pTarget = ct.pTarget;
#if defined(_M_X64) || defined(__x86_64__)
pHook->pDetour = ct.pRelay;
#else
pHook->pDetour = ct.pDetour;
#endif
pHook->pTrampoline = ct.pTrampoline;
pHook->patchAbove = ct.patchAbove;
pHook->isEnabled = FALSE;
pHook->queueEnable = FALSE;
pHook->nIP = ct.nIP;
memcpy(pHook->oldIPs, ct.oldIPs, ARRAYSIZE(ct.oldIPs));
memcpy(pHook->newIPs, ct.newIPs, ARRAYSIZE(ct.newIPs));
// Back up the target function.
if (ct.patchAbove)
{
memcpy(
pHook->backup,
(LPBYTE)pTarget - sizeof(JMP_REL),
sizeof(JMP_REL) + sizeof(JMP_REL_SHORT));
}
else
{
memcpy(pHook->backup, pTarget, sizeof(JMP_REL));
}
if (ppOriginal != NULL)
*ppOriginal = pHook->pTrampoline;
}
else
{
status = MH_ERROR_MEMORY_ALLOC;
}
}
else
{
status = MH_ERROR_UNSUPPORTED_FUNCTION;
}
if (status != MH_OK)
{
FreeBuffer(pBuffer);
}
}
else
{
status = MH_ERROR_MEMORY_ALLOC;
}
}
else
{
status = MH_ERROR_ALREADY_CREATED;
}
}
else
{
status = MH_ERROR_NOT_EXECUTABLE;
}
}
else
{
status = MH_ERROR_NOT_INITIALIZED;
}
LeaveSpinLock();
return status;
}
//-------------------------------------------------------------------------
MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget)
{
MH_STATUS status = MH_OK;
EnterSpinLock();
if (g_hHeap != NULL)
{
UINT pos = FindHookEntry(pTarget);
if (pos != INVALID_HOOK_POS)
{
if (g_hooks.pItems[pos].isEnabled)
{
FROZEN_THREADS threads;
Freeze(&threads, pos, ACTION_DISABLE);
status = EnableHookLL(pos, FALSE);
Unfreeze(&threads);
}
if (status == MH_OK)
{
FreeBuffer(g_hooks.pItems[pos].pTrampoline);
DeleteHookEntry(pos);
}
}
else
{
status = MH_ERROR_NOT_CREATED;
}
}
else
{
status = MH_ERROR_NOT_INITIALIZED;
}
LeaveSpinLock();
return status;
}
//-------------------------------------------------------------------------
static MH_STATUS EnableHook(LPVOID pTarget, BOOL enable)
{
MH_STATUS status = MH_OK;
EnterSpinLock();
if (g_hHeap != NULL)
{
if (pTarget == MH_ALL_HOOKS)
{
status = EnableAllHooksLL(enable);
}
else
{
FROZEN_THREADS threads;
UINT pos = FindHookEntry(pTarget);
if (pos != INVALID_HOOK_POS)
{
if (g_hooks.pItems[pos].isEnabled != enable)
{
Freeze(&threads, pos, ACTION_ENABLE);
status = EnableHookLL(pos, enable);
Unfreeze(&threads);
}
else
{
status = enable ? MH_ERROR_ENABLED : MH_ERROR_DISABLED;
}
}
else
{
status = MH_ERROR_NOT_CREATED;
}
}
}
else
{
status = MH_ERROR_NOT_INITIALIZED;
}
LeaveSpinLock();
return status;
}
//-------------------------------------------------------------------------
MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget)
{
return EnableHook(pTarget, TRUE);
}
//-------------------------------------------------------------------------
MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget)
{
return EnableHook(pTarget, FALSE);
}
//-------------------------------------------------------------------------
static MH_STATUS QueueHook(LPVOID pTarget, BOOL queueEnable)
{
MH_STATUS status = MH_OK;
EnterSpinLock();
if (g_hHeap != NULL)
{
if (pTarget == MH_ALL_HOOKS)
{
UINT i;
for (i = 0; i < g_hooks.size; ++i)
g_hooks.pItems[i].queueEnable = queueEnable;
}
else
{
UINT pos = FindHookEntry(pTarget);
if (pos != INVALID_HOOK_POS)
{
g_hooks.pItems[pos].queueEnable = queueEnable;
}
else
{
status = MH_ERROR_NOT_CREATED;
}
}
}
else
{
status = MH_ERROR_NOT_INITIALIZED;
}
LeaveSpinLock();
return status;
}
//-------------------------------------------------------------------------
MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget)
{
return QueueHook(pTarget, TRUE);
}
//-------------------------------------------------------------------------
MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget)
{
return QueueHook(pTarget, FALSE);
}
//-------------------------------------------------------------------------
MH_STATUS WINAPI MH_ApplyQueued(VOID)
{
MH_STATUS status = MH_OK;
UINT i, first = INVALID_HOOK_POS;
EnterSpinLock();
if (g_hHeap != NULL)
{
for (i = 0; i < g_hooks.size; ++i)
{
if (g_hooks.pItems[i].isEnabled != g_hooks.pItems[i].queueEnable)
{
first = i;
break;
}
}
if (first != INVALID_HOOK_POS)
{
FROZEN_THREADS threads;
Freeze(&threads, ALL_HOOKS_POS, ACTION_APPLY_QUEUED);
for (i = first; i < g_hooks.size; ++i)
{
PHOOK_ENTRY pHook = &g_hooks.pItems[i];
if (pHook->isEnabled != pHook->queueEnable)
{
status = EnableHookLL(i, pHook->queueEnable);
if (status != MH_OK)
break;
}
}
Unfreeze(&threads);
}
}
else
{
status = MH_ERROR_NOT_INITIALIZED;
}
LeaveSpinLock();
return status;
}
//-------------------------------------------------------------------------
MH_STATUS WINAPI MH_CreateHookApiEx(
LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour,
LPVOID *ppOriginal, LPVOID *ppTarget)
{
HMODULE hModule;
LPVOID pTarget;
hModule = GetModuleHandleW(pszModule);
if (hModule == NULL)
return MH_ERROR_MODULE_NOT_FOUND;
pTarget = (LPVOID)GetProcAddress(hModule, pszProcName);
if (pTarget == NULL)
return MH_ERROR_FUNCTION_NOT_FOUND;
if(ppTarget != NULL)
*ppTarget = pTarget;
return MH_CreateHook(pTarget, pDetour, ppOriginal);
}
//-------------------------------------------------------------------------
MH_STATUS WINAPI MH_CreateHookApi(
LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal)
{
return MH_CreateHookApiEx(pszModule, pszProcName, pDetour, ppOriginal, NULL);
}
//-------------------------------------------------------------------------
const char * WINAPI MH_StatusToString(MH_STATUS status)
{
#define MH_ST2STR(x) \
case x: \
return #x;
switch (status) {
MH_ST2STR(MH_UNKNOWN)
MH_ST2STR(MH_OK)
MH_ST2STR(MH_ERROR_ALREADY_INITIALIZED)
MH_ST2STR(MH_ERROR_NOT_INITIALIZED)
MH_ST2STR(MH_ERROR_ALREADY_CREATED)
MH_ST2STR(MH_ERROR_NOT_CREATED)
MH_ST2STR(MH_ERROR_ENABLED)
MH_ST2STR(MH_ERROR_DISABLED)
MH_ST2STR(MH_ERROR_NOT_EXECUTABLE)
MH_ST2STR(MH_ERROR_UNSUPPORTED_FUNCTION)
MH_ST2STR(MH_ERROR_MEMORY_ALLOC)
MH_ST2STR(MH_ERROR_MEMORY_PROTECT)
MH_ST2STR(MH_ERROR_MODULE_NOT_FOUND)
MH_ST2STR(MH_ERROR_FUNCTION_NOT_FOUND)
}
#undef MH_ST2STR
return "(unknown)";
}

View File

@@ -0,0 +1,320 @@
/*
* MinHook - The Minimalistic API Hooking Library for x64/x86
* Copyright (C) 2009-2017 Tsuda Kageyu.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <windows.h>
#ifdef _MSC_VER
#include <intrin.h>
#endif
#ifndef ARRAYSIZE
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif
#if defined(_M_X64) || defined(__x86_64__)
#include "./hde/hde64.h"
typedef hde64s HDE;
#define HDE_DISASM(code, hs) hde64_disasm(code, hs)
#else
#include "./hde/hde32.h"
typedef hde32s HDE;
#define HDE_DISASM(code, hs) hde32_disasm(code, hs)
#endif
#include "trampoline.h"
#include "buffer.h"
// Maximum size of a trampoline function.
#if defined(_M_X64) || defined(__x86_64__)
#define TRAMPOLINE_MAX_SIZE (MEMORY_SLOT_SIZE - sizeof(JMP_ABS))
#else
#define TRAMPOLINE_MAX_SIZE MEMORY_SLOT_SIZE
#endif
//-------------------------------------------------------------------------
static BOOL IsCodePadding(LPBYTE pInst, UINT size)
{
UINT i;
if (pInst[0] != 0x00 && pInst[0] != 0x90 && pInst[0] != 0xCC)
return FALSE;
for (i = 1; i < size; ++i)
{
if (pInst[i] != pInst[0])
return FALSE;
}
return TRUE;
}
//-------------------------------------------------------------------------
BOOL CreateTrampolineFunction(PTRAMPOLINE ct)
{
#if defined(_M_X64) || defined(__x86_64__)
CALL_ABS call = {
0xFF, 0x15, 0x00000002, // FF15 00000002: CALL [RIP+8]
0xEB, 0x08, // EB 08: JMP +10
0x0000000000000000ULL // Absolute destination address
};
JMP_ABS jmp = {
0xFF, 0x25, 0x00000000, // FF25 00000000: JMP [RIP+6]
0x0000000000000000ULL // Absolute destination address
};
JCC_ABS jcc = {
0x70, 0x0E, // 7* 0E: J** +16
0xFF, 0x25, 0x00000000, // FF25 00000000: JMP [RIP+6]
0x0000000000000000ULL // Absolute destination address
};
#else
CALL_REL call = {
0xE8, // E8 xxxxxxxx: CALL +5+xxxxxxxx
0x00000000 // Relative destination address
};
JMP_REL jmp = {
0xE9, // E9 xxxxxxxx: JMP +5+xxxxxxxx
0x00000000 // Relative destination address
};
JCC_REL jcc = {
0x0F, 0x80, // 0F8* xxxxxxxx: J** +6+xxxxxxxx
0x00000000 // Relative destination address
};
#endif
UINT8 oldPos = 0;
UINT8 newPos = 0;
ULONG_PTR jmpDest = 0; // Destination address of an internal jump.
BOOL finished = FALSE; // Is the function completed?
#if defined(_M_X64) || defined(__x86_64__)
UINT8 instBuf[16];
#endif
ct->patchAbove = FALSE;
ct->nIP = 0;
do
{
HDE hs;
UINT copySize;
LPVOID pCopySrc;
ULONG_PTR pOldInst = (ULONG_PTR)ct->pTarget + oldPos;
ULONG_PTR pNewInst = (ULONG_PTR)ct->pTrampoline + newPos;
copySize = HDE_DISASM((LPVOID)pOldInst, &hs);
if (hs.flags & F_ERROR)
return FALSE;
pCopySrc = (LPVOID)pOldInst;
if (oldPos >= sizeof(JMP_REL))
{
// The trampoline function is long enough.
// Complete the function with the jump to the target function.
#if defined(_M_X64) || defined(__x86_64__)
jmp.address = pOldInst;
#else
jmp.operand = (UINT32)(pOldInst - (pNewInst + sizeof(jmp)));
#endif
pCopySrc = &jmp;
copySize = sizeof(jmp);
finished = TRUE;
}
#if defined(_M_X64) || defined(__x86_64__)
else if ((hs.modrm & 0xC7) == 0x05)
{
// Instructions using RIP relative addressing. (ModR/M = 00???101B)
// Modify the RIP relative address.
PUINT32 pRelAddr;
// Avoid using memcpy to reduce the footprint.
#ifndef _MSC_VER
memcpy(instBuf, (LPBYTE)pOldInst, copySize);
#else
__movsb(instBuf, (LPBYTE)pOldInst, copySize);
#endif
pCopySrc = instBuf;
// Relative address is stored at (instruction length - immediate value length - 4).
pRelAddr = (PUINT32)(instBuf + hs.len - ((hs.flags & 0x3C) >> 2) - 4);
*pRelAddr
= (UINT32)((pOldInst + hs.len + (INT32)hs.disp.disp32) - (pNewInst + hs.len));
// Complete the function if JMP (FF /4).
if (hs.opcode == 0xFF && hs.modrm_reg == 4)
finished = TRUE;
}
#endif
else if (hs.opcode == 0xE8)
{
// Direct relative CALL
ULONG_PTR dest = pOldInst + hs.len + (INT32)hs.imm.imm32;
#if defined(_M_X64) || defined(__x86_64__)
call.address = dest;
#else
call.operand = (UINT32)(dest - (pNewInst + sizeof(call)));
#endif
pCopySrc = &call;
copySize = sizeof(call);
}
else if ((hs.opcode & 0xFD) == 0xE9)
{
// Direct relative JMP (EB or E9)
ULONG_PTR dest = pOldInst + hs.len;
if (hs.opcode == 0xEB) // isShort jmp
dest += (INT8)hs.imm.imm8;
else
dest += (INT32)hs.imm.imm32;
// Simply copy an internal jump.
if ((ULONG_PTR)ct->pTarget <= dest
&& dest < ((ULONG_PTR)ct->pTarget + sizeof(JMP_REL)))
{
if (jmpDest < dest)
jmpDest = dest;
}
else
{
#if defined(_M_X64) || defined(__x86_64__)
jmp.address = dest;
#else
jmp.operand = (UINT32)(dest - (pNewInst + sizeof(jmp)));
#endif
pCopySrc = &jmp;
copySize = sizeof(jmp);
// Exit the function If it is not in the branch
finished = (pOldInst >= jmpDest);
}
}
else if ((hs.opcode & 0xF0) == 0x70
|| (hs.opcode & 0xFC) == 0xE0
|| (hs.opcode2 & 0xF0) == 0x80)
{
// Direct relative Jcc
ULONG_PTR dest = pOldInst + hs.len;
if ((hs.opcode & 0xF0) == 0x70 // Jcc
|| (hs.opcode & 0xFC) == 0xE0) // LOOPNZ/LOOPZ/LOOP/JECXZ
dest += (INT8)hs.imm.imm8;
else
dest += (INT32)hs.imm.imm32;
// Simply copy an internal jump.
if ((ULONG_PTR)ct->pTarget <= dest
&& dest < ((ULONG_PTR)ct->pTarget + sizeof(JMP_REL)))
{
if (jmpDest < dest)
jmpDest = dest;
}
else if ((hs.opcode & 0xFC) == 0xE0)
{
// LOOPNZ/LOOPZ/LOOP/JCXZ/JECXZ to the outside are not supported.
return FALSE;
}
else
{
UINT8 cond = ((hs.opcode != 0x0F ? hs.opcode : hs.opcode2) & 0x0F);
#if defined(_M_X64) || defined(__x86_64__)
// Invert the condition in x64 mode to simplify the conditional jump logic.
jcc.opcode = 0x71 ^ cond;
jcc.address = dest;
#else
jcc.opcode1 = 0x80 | cond;
jcc.operand = (UINT32)(dest - (pNewInst + sizeof(jcc)));
#endif
pCopySrc = &jcc;
copySize = sizeof(jcc);
}
}
else if ((hs.opcode & 0xFE) == 0xC2)
{
// RET (C2 or C3)
// Complete the function if not in a branch.
finished = (pOldInst >= jmpDest);
}
// Can't alter the instruction length in a branch.
if (pOldInst < jmpDest && copySize != hs.len)
return FALSE;
// Trampoline function is too large.
if ((newPos + copySize) > TRAMPOLINE_MAX_SIZE)
return FALSE;
// Trampoline function has too many instructions.
if (ct->nIP >= ARRAYSIZE(ct->oldIPs))
return FALSE;
ct->oldIPs[ct->nIP] = oldPos;
ct->newIPs[ct->nIP] = newPos;
ct->nIP++;
// Avoid using memcpy to reduce the footprint.
#ifndef _MSC_VER
memcpy((LPBYTE)ct->pTrampoline + newPos, pCopySrc, copySize);
#else
__movsb((LPBYTE)ct->pTrampoline + newPos, pCopySrc, copySize);
#endif
newPos += copySize;
oldPos += hs.len;
}
while (!finished);
// Is there enough place for a long jump?
if (oldPos < sizeof(JMP_REL)
&& !IsCodePadding((LPBYTE)ct->pTarget + oldPos, sizeof(JMP_REL) - oldPos))
{
// Is there enough place for a short jump?
if (oldPos < sizeof(JMP_REL_SHORT)
&& !IsCodePadding((LPBYTE)ct->pTarget + oldPos, sizeof(JMP_REL_SHORT) - oldPos))
{
return FALSE;
}
// Can we place the long jump above the function?
if (!IsExecutableAddress((LPBYTE)ct->pTarget - sizeof(JMP_REL)))
return FALSE;
if (!IsCodePadding((LPBYTE)ct->pTarget - sizeof(JMP_REL), sizeof(JMP_REL)))
return FALSE;
ct->patchAbove = TRUE;
}
#if defined(_M_X64) || defined(__x86_64__)
// Create a relay function.
jmp.address = (ULONG_PTR)ct->pDetour;
ct->pRelay = (LPBYTE)ct->pTrampoline + newPos;
memcpy(ct->pRelay, &jmp, sizeof(jmp));
#endif
return TRUE;
}

View File

@@ -0,0 +1,105 @@
/*
* MinHook - The Minimalistic API Hooking Library for x64/x86
* Copyright (C) 2009-2017 Tsuda Kageyu.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#pragma pack(push, 1)
// Structs for writing x86/x64 instructions.
// 8-bit relative jump.
typedef struct _JMP_REL_SHORT
{
UINT8 opcode; // EB xx: JMP +2+xx
UINT8 operand;
} JMP_REL_SHORT, *PJMP_REL_SHORT;
// 32-bit direct relative jump/call.
typedef struct _JMP_REL
{
UINT8 opcode; // E9/E8 xxxxxxxx: JMP/CALL +5+xxxxxxxx
UINT32 operand; // Relative destination address
} JMP_REL, *PJMP_REL, CALL_REL;
// 64-bit indirect absolute jump.
typedef struct _JMP_ABS
{
UINT8 opcode0; // FF25 00000000: JMP [+6]
UINT8 opcode1;
UINT32 dummy;
UINT64 address; // Absolute destination address
} JMP_ABS, *PJMP_ABS;
// 64-bit indirect absolute call.
typedef struct _CALL_ABS
{
UINT8 opcode0; // FF15 00000002: CALL [+6]
UINT8 opcode1;
UINT32 dummy0;
UINT8 dummy1; // EB 08: JMP +10
UINT8 dummy2;
UINT64 address; // Absolute destination address
} CALL_ABS;
// 32-bit direct relative conditional jumps.
typedef struct _JCC_REL
{
UINT8 opcode0; // 0F8* xxxxxxxx: J** +6+xxxxxxxx
UINT8 opcode1;
UINT32 operand; // Relative destination address
} JCC_REL;
// 64bit indirect absolute conditional jumps that x64 lacks.
typedef struct _JCC_ABS
{
UINT8 opcode; // 7* 0E: J** +16
UINT8 dummy0;
UINT8 dummy1; // FF25 00000000: JMP [+6]
UINT8 dummy2;
UINT32 dummy3;
UINT64 address; // Absolute destination address
} JCC_ABS;
#pragma pack(pop)
typedef struct _TRAMPOLINE
{
LPVOID pTarget; // [In] Address of the target function.
LPVOID pDetour; // [In] Address of the detour function.
LPVOID pTrampoline; // [In] Buffer address for the trampoline and relay function.
#if defined(_M_X64) || defined(__x86_64__)
LPVOID pRelay; // [Out] Address of the relay function.
#endif
BOOL patchAbove; // [Out] Should use the hot patch area?
UINT nIP; // [Out] Number of the instruction boundaries.
UINT8 oldIPs[8]; // [Out] Instruction boundaries of the target function.
UINT8 newIPs[8]; // [Out] Instruction boundaries of the trampoline function.
} TRAMPOLINE, *PTRAMPOLINE;
BOOL CreateTrampolineFunction(PTRAMPOLINE ct);

View File

@@ -0,0 +1,123 @@
//-----------------------------------------------------------------------------
// COMPILE-TIME OPTIONS FOR DEAR IMGUI
// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
//-----------------------------------------------------------------------------
// A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it)
// B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template.
//-----------------------------------------------------------------------------
// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
// Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using.
//-----------------------------------------------------------------------------
#pragma once
//---- Define assertion handler. Defaults to calling assert().
// If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
// DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
//#define IMGUI_API __declspec( dllexport )
//#define IMGUI_API __declspec( dllimport )
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names.
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
//---- Disable all of Dear ImGui or don't implement standard windows.
// It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp.
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. Not recommended.
//#define IMGUI_DISABLE_METRICS_WINDOW // Disable metrics/debugger and other debug tools: ShowMetricsWindow() and ShowStackToolWindow() will be empty.
//---- Don't implement some functions to reduce linkage requirements.
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
//#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW)
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime).
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
//---- Include imgui_user.h at the end of imgui.h as a convenience
//#define IMGUI_INCLUDE_IMGUI_USER_H
//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
//#define IMGUI_USE_BGRA_PACKED_COLOR
//---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
//#define IMGUI_USE_WCHAR32
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
//---- Use stb_printf's faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
// Requires 'stb_sprintf.h' to be available in the include path. Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf.
// #define IMGUI_USE_STB_SPRINTF
//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
//#define IMGUI_ENABLE_FREETYPE
//---- Use stb_truetype to build and rasterize the font atlas (default)
// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
//#define IMGUI_ENABLE_STB_TRUETYPE
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
// This will be inlined as part of ImVec2 and ImVec4 class declarations.
/*
#define IM_VEC2_CLASS_EXTRA \
ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \
operator MyVec2() const { return MyVec2(x,y); }
#define IM_VEC4_CLASS_EXTRA \
ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \
operator MyVec4() const { return MyVec4(x,y,z,w); }
*/
//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
// Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
//#define ImDrawIdx unsigned int
//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
//struct ImDrawList;
//struct ImDrawCmd;
//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
//#define ImDrawCallback MyImDrawCallback
//---- Debug Tools: Macro to break in Debugger
// (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
//#define IM_DEBUG_BREAK IM_ASSERT(0)
//#define IM_DEBUG_BREAK __debugbreak()
//---- Debug Tools: Have the Item Picker break in the ItemAdd() function instead of ItemHoverable(),
// (which comes earlier in the code, will catch a few extra items, allow picking items other than Hovered one.)
// This adds a small runtime cost which is why it is not enabled by default.
//#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX
//---- Debug Tools: Enable slower asserts
//#define IMGUI_DEBUG_PARANOID
//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
/*
namespace ImGui
{
void MyFunction(const char* name, const MyMatrix44& v);
}
*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,594 @@
// dear imgui: Renderer Backend for DirectX11
// This needs to be used along with a Platform Backend (e.g. Win32)
// Implemented features:
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-05-19: DirectX11: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
// 2021-02-18: DirectX11: Change blending equation to preserve alpha in output buffer.
// 2019-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled).
// 2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore.
// 2019-05-29: DirectX11: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
// 2019-04-30: DirectX11: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
// 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile().
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
// 2018-08-01: DirectX11: Querying for IDXGIFactory instead of IDXGIFactory1 to increase compatibility.
// 2018-07-13: DirectX11: Fixed unreleased resources in Init and Shutdown functions.
// 2018-06-08: Misc: Extracted imgui_impl_dx11.cpp/.h away from the old combined DX11+Win32 example.
// 2018-06-08: DirectX11: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX11_RenderDrawData() in the .h file so you can call it yourself.
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
// 2016-05-07: DirectX11: Disabling depth-write.
#include "imgui.h"
#include "imgui_impl_dx11.h"
// DirectX
#include <stdio.h>
#include <d3d11.h>
#include <d3dcompiler.h>
#ifdef _MSC_VER
#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
#endif
// DirectX11 data
struct ImGui_ImplDX11_Data
{
ID3D11Device* pd3dDevice;
ID3D11DeviceContext* pd3dDeviceContext;
IDXGIFactory* pFactory;
ID3D11Buffer* pVB;
ID3D11Buffer* pIB;
ID3D11VertexShader* pVertexShader;
ID3D11InputLayout* pInputLayout;
ID3D11Buffer* pVertexConstantBuffer;
ID3D11PixelShader* pPixelShader;
ID3D11SamplerState* pFontSampler;
ID3D11ShaderResourceView* pFontTextureView;
ID3D11RasterizerState* pRasterizerState;
ID3D11BlendState* pBlendState;
ID3D11DepthStencilState* pDepthStencilState;
int VertexBufferSize;
int IndexBufferSize;
ImGui_ImplDX11_Data() { memset(this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
};
struct VERTEX_CONSTANT_BUFFER
{
float mvp[4][4];
};
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
static ImGui_ImplDX11_Data* ImGui_ImplDX11_GetBackendData()
{
return ImGui::GetCurrentContext() ? (ImGui_ImplDX11_Data*)ImGui::GetIO().BackendRendererUserData : NULL;
}
// Functions
static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* ctx)
{
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
// Setup viewport
D3D11_VIEWPORT vp;
memset(&vp, 0, sizeof(D3D11_VIEWPORT));
vp.Width = draw_data->DisplaySize.x;
vp.Height = draw_data->DisplaySize.y;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = vp.TopLeftY = 0;
ctx->RSSetViewports(1, &vp);
// Setup shader and vertex buffers
unsigned int stride = sizeof(ImDrawVert);
unsigned int offset = 0;
ctx->IASetInputLayout(bd->pInputLayout);
ctx->IASetVertexBuffers(0, 1, &bd->pVB, &stride, &offset);
ctx->IASetIndexBuffer(bd->pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ctx->VSSetShader(bd->pVertexShader, NULL, 0);
ctx->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer);
ctx->PSSetShader(bd->pPixelShader, NULL, 0);
ctx->PSSetSamplers(0, 1, &bd->pFontSampler);
ctx->GSSetShader(NULL, NULL, 0);
ctx->HSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used..
ctx->DSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used..
ctx->CSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used..
// Setup blend state
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
ctx->OMSetBlendState(bd->pBlendState, blend_factor, 0xffffffff);
ctx->OMSetDepthStencilState(bd->pDepthStencilState, 0);
ctx->RSSetState(bd->pRasterizerState);
}
// Render function
void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
{
// Avoid rendering when minimized
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
return;
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
ID3D11DeviceContext* ctx = bd->pd3dDeviceContext;
// Create and grow vertex/index buffers if needed
if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount)
{
if (bd->pVB) { bd->pVB->Release(); bd->pVB = NULL; }
bd->VertexBufferSize = draw_data->TotalVtxCount + 5000;
D3D11_BUFFER_DESC desc;
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.ByteWidth = bd->VertexBufferSize * sizeof(ImDrawVert);
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
if (bd->pd3dDevice->CreateBuffer(&desc, NULL, &bd->pVB) < 0)
return;
}
if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount)
{
if (bd->pIB) { bd->pIB->Release(); bd->pIB = NULL; }
bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
D3D11_BUFFER_DESC desc;
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.ByteWidth = bd->IndexBufferSize * sizeof(ImDrawIdx);
desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
if (bd->pd3dDevice->CreateBuffer(&desc, NULL, &bd->pIB) < 0)
return;
}
// Upload vertex/index data into a single contiguous GPU buffer
D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource;
if (ctx->Map(bd->pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)
return;
if (ctx->Map(bd->pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK)
return;
ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData;
ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData;
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
vtx_dst += cmd_list->VtxBuffer.Size;
idx_dst += cmd_list->IdxBuffer.Size;
}
ctx->Unmap(bd->pVB, 0);
ctx->Unmap(bd->pIB, 0);
// Setup orthographic projection matrix into our constant buffer
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
{
D3D11_MAPPED_SUBRESOURCE mapped_resource;
if (ctx->Map(bd->pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
return;
VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData;
float L = draw_data->DisplayPos.x;
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
float T = draw_data->DisplayPos.y;
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
float mvp[4][4] =
{
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.5f, 0.0f },
{ (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
};
memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
ctx->Unmap(bd->pVertexConstantBuffer, 0);
}
// Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!)
struct BACKUP_DX11_STATE
{
UINT ScissorRectsCount, ViewportsCount;
D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
ID3D11RasterizerState* RS;
ID3D11BlendState* BlendState;
FLOAT BlendFactor[4];
UINT SampleMask;
UINT StencilRef;
ID3D11DepthStencilState* DepthStencilState;
ID3D11ShaderResourceView* PSShaderResource;
ID3D11SamplerState* PSSampler;
ID3D11PixelShader* PS;
ID3D11VertexShader* VS;
ID3D11GeometryShader* GS;
UINT PSInstancesCount, VSInstancesCount, GSInstancesCount;
ID3D11ClassInstance *PSInstances[256], *VSInstances[256], *GSInstances[256]; // 256 is max according to PSSetShader documentation
D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology;
ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer;
UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset;
DXGI_FORMAT IndexBufferFormat;
ID3D11InputLayout* InputLayout;
};
BACKUP_DX11_STATE old = {};
old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects);
ctx->RSGetViewports(&old.ViewportsCount, old.Viewports);
ctx->RSGetState(&old.RS);
ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask);
ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef);
ctx->PSGetShaderResources(0, 1, &old.PSShaderResource);
ctx->PSGetSamplers(0, 1, &old.PSSampler);
old.PSInstancesCount = old.VSInstancesCount = old.GSInstancesCount = 256;
ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount);
ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount);
ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer);
ctx->GSGetShader(&old.GS, old.GSInstances, &old.GSInstancesCount);
ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology);
ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset);
ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
ctx->IAGetInputLayout(&old.InputLayout);
// Setup desired DX state
ImGui_ImplDX11_SetupRenderState(draw_data, ctx);
// Render command lists
// (Because we merged all buffers into a single one, we maintain our own offset into them)
int global_idx_offset = 0;
int global_vtx_offset = 0;
ImVec2 clip_off = draw_data->DisplayPos;
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback != NULL)
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
ImGui_ImplDX11_SetupRenderState(draw_data, ctx);
else
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
// Project scissor/clipping rectangles into framebuffer space
ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
// Apply scissor/clipping rectangle
const D3D11_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
ctx->RSSetScissorRects(1, &r);
// Bind texture, Draw
ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->GetTexID();
ctx->PSSetShaderResources(0, 1, &texture_srv);
ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
}
}
global_idx_offset += cmd_list->IdxBuffer.Size;
global_vtx_offset += cmd_list->VtxBuffer.Size;
}
// Restore modified DX state
ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
ctx->RSSetViewports(old.ViewportsCount, old.Viewports);
ctx->RSSetState(old.RS); if (old.RS) old.RS->Release();
ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release();
ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release();
ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release();
ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release();
ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release();
for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release();
ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release();
ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();
ctx->GSSetShader(old.GS, old.GSInstances, old.GSInstancesCount); if (old.GS) old.GS->Release();
for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release();
ctx->IASetPrimitiveTopology(old.PrimitiveTopology);
ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release();
ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release();
ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
}
static void ImGui_ImplDX11_CreateFontsTexture()
{
// Build texture atlas
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
unsigned char* pixels;
int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
// Upload texture to graphics system
{
D3D11_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.Width = width;
desc.Height = height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0;
ID3D11Texture2D* pTexture = NULL;
D3D11_SUBRESOURCE_DATA subResource;
subResource.pSysMem = pixels;
subResource.SysMemPitch = desc.Width * 4;
subResource.SysMemSlicePitch = 0;
bd->pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
IM_ASSERT(pTexture != NULL);
// Create texture view
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
ZeroMemory(&srvDesc, sizeof(srvDesc));
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = desc.MipLevels;
srvDesc.Texture2D.MostDetailedMip = 0;
bd->pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &bd->pFontTextureView);
pTexture->Release();
}
// Store our identifier
io.Fonts->SetTexID((ImTextureID)bd->pFontTextureView);
// Create texture sampler
{
D3D11_SAMPLER_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
desc.MipLODBias = 0.f;
desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
desc.MinLOD = 0.f;
desc.MaxLOD = 0.f;
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler);
}
}
bool ImGui_ImplDX11_CreateDeviceObjects()
{
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
if (!bd->pd3dDevice)
return false;
if (bd->pFontSampler)
ImGui_ImplDX11_InvalidateDeviceObjects();
// By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
// If you would like to use this DX11 sample code but remove this dependency you can:
// 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution]
// 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL.
// See https://github.com/ocornut/imgui/pull/638 for sources and details.
// Create the vertex shader
{
static const char* vertexShader =
"cbuffer vertexBuffer : register(b0) \
{\
float4x4 ProjectionMatrix; \
};\
struct VS_INPUT\
{\
float2 pos : POSITION;\
float4 col : COLOR0;\
float2 uv : TEXCOORD0;\
};\
\
struct PS_INPUT\
{\
float4 pos : SV_POSITION;\
float4 col : COLOR0;\
float2 uv : TEXCOORD0;\
};\
\
PS_INPUT main(VS_INPUT input)\
{\
PS_INPUT output;\
output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\
output.col = input.col;\
output.uv = input.uv;\
return output;\
}";
ID3DBlob* vertexShaderBlob;
if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &vertexShaderBlob, NULL)))
return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
if (bd->pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), NULL, &bd->pVertexShader) != S_OK)
{
vertexShaderBlob->Release();
return false;
}
// Create the input layout
D3D11_INPUT_ELEMENT_DESC local_layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, pos), D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, uv), D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
if (bd->pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &bd->pInputLayout) != S_OK)
{
vertexShaderBlob->Release();
return false;
}
vertexShaderBlob->Release();
// Create the constant buffer
{
D3D11_BUFFER_DESC desc;
desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
bd->pd3dDevice->CreateBuffer(&desc, NULL, &bd->pVertexConstantBuffer);
}
}
// Create the pixel shader
{
static const char* pixelShader =
"struct PS_INPUT\
{\
float4 pos : SV_POSITION;\
float4 col : COLOR0;\
float2 uv : TEXCOORD0;\
};\
sampler sampler0;\
Texture2D texture0;\
\
float4 main(PS_INPUT input) : SV_Target\
{\
float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \
return out_col; \
}";
ID3DBlob* pixelShaderBlob;
if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &pixelShaderBlob, NULL)))
return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
if (bd->pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), NULL, &bd->pPixelShader) != S_OK)
{
pixelShaderBlob->Release();
return false;
}
pixelShaderBlob->Release();
}
// Create the blending setup
{
D3D11_BLEND_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.AlphaToCoverageEnable = false;
desc.RenderTarget[0].BlendEnable = true;
desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
bd->pd3dDevice->CreateBlendState(&desc, &bd->pBlendState);
}
// Create the rasterizer state
{
D3D11_RASTERIZER_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.FillMode = D3D11_FILL_SOLID;
desc.CullMode = D3D11_CULL_NONE;
desc.ScissorEnable = true;
desc.DepthClipEnable = true;
bd->pd3dDevice->CreateRasterizerState(&desc, &bd->pRasterizerState);
}
// Create depth-stencil State
{
D3D11_DEPTH_STENCIL_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.DepthEnable = false;
desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
desc.DepthFunc = D3D11_COMPARISON_ALWAYS;
desc.StencilEnable = false;
desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
desc.BackFace = desc.FrontFace;
bd->pd3dDevice->CreateDepthStencilState(&desc, &bd->pDepthStencilState);
}
ImGui_ImplDX11_CreateFontsTexture();
return true;
}
void ImGui_ImplDX11_InvalidateDeviceObjects()
{
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
if (!bd->pd3dDevice)
return;
if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = NULL; }
if (bd->pFontTextureView) { bd->pFontTextureView->Release(); bd->pFontTextureView = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied data->pFontTextureView to io.Fonts->TexID so let's clear that as well.
if (bd->pIB) { bd->pIB->Release(); bd->pIB = NULL; }
if (bd->pVB) { bd->pVB->Release(); bd->pVB = NULL; }
if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = NULL; }
if (bd->pDepthStencilState) { bd->pDepthStencilState->Release(); bd->pDepthStencilState = NULL; }
if (bd->pRasterizerState) { bd->pRasterizerState->Release(); bd->pRasterizerState = NULL; }
if (bd->pPixelShader) { bd->pPixelShader->Release(); bd->pPixelShader = NULL; }
if (bd->pVertexConstantBuffer) { bd->pVertexConstantBuffer->Release(); bd->pVertexConstantBuffer = NULL; }
if (bd->pInputLayout) { bd->pInputLayout->Release(); bd->pInputLayout = NULL; }
if (bd->pVertexShader) { bd->pVertexShader->Release(); bd->pVertexShader = NULL; }
}
bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context)
{
ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
// Setup backend capabilities flags
ImGui_ImplDX11_Data* bd = IM_NEW(ImGui_ImplDX11_Data)();
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_dx11";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
// Get factory from device
IDXGIDevice* pDXGIDevice = NULL;
IDXGIAdapter* pDXGIAdapter = NULL;
IDXGIFactory* pFactory = NULL;
if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK)
if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK)
if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK)
{
bd->pd3dDevice = device;
bd->pd3dDeviceContext = device_context;
bd->pFactory = pFactory;
}
if (pDXGIDevice) pDXGIDevice->Release();
if (pDXGIAdapter) pDXGIAdapter->Release();
bd->pd3dDevice->AddRef();
bd->pd3dDeviceContext->AddRef();
return true;
}
void ImGui_ImplDX11_Shutdown()
{
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplDX11_InvalidateDeviceObjects();
if (bd->pFactory) { bd->pFactory->Release(); }
if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
if (bd->pd3dDeviceContext) { bd->pd3dDeviceContext->Release(); }
io.BackendRendererName = NULL;
io.BackendRendererUserData = NULL;
IM_DELETE(bd);
}
void ImGui_ImplDX11_NewFrame()
{
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
IM_ASSERT(bd != NULL && "Did you call ImGui_ImplDX11_Init()?");
if (!bd->pFontSampler)
ImGui_ImplDX11_CreateDeviceObjects();
}

View File

@@ -0,0 +1,26 @@
// dear imgui: Renderer Backend for DirectX11
// This needs to be used along with a Platform Backend (e.g. Win32)
// Implemented features:
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
#pragma once
#include "imgui.h" // IMGUI_IMPL_API
struct ID3D11Device;
struct ID3D11DeviceContext;
IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context);
IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown();
IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame();
IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data);
// Use if you want to reset your rendering device without losing Dear ImGui state.
IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects();
IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects();

View File

@@ -0,0 +1,629 @@
// dear imgui: Platform Backend for Windows (standard windows API for 32 and 64 bits applications)
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
// Implemented features:
// [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui)
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE).
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
#include "imgui.h"
#include "imgui_impl_win32.h"
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <tchar.h>
#include <dwmapi.h>
// Configuration flags to add in your imconfig.h file:
//#define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD // Disable gamepad support. This was meaningful before <1.81 but we now load XInput dynamically so the option is now less relevant.
// Using XInput for gamepad (will load DLL dynamically)
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
#include <xinput.h>
typedef DWORD (WINAPI *PFN_XInputGetCapabilities)(DWORD, DWORD, XINPUT_CAPABILITIES*);
typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*);
#endif
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2021-12-16: Inputs: Fill VK_LCONTROL/VK_RCONTROL/VK_LSHIFT/VK_RSHIFT/VK_LMENU/VK_RMENU for completeness.
// 2021-08-17: Calling io.AddFocusEvent() on WM_SETFOCUS/WM_KILLFOCUS messages.
// 2021-08-02: Inputs: Fixed keyboard modifiers being reported when host window doesn't have focus.
// 2021-07-29: Inputs: MousePos is correctly reported when the host platform window is hovered but not focused (using TrackMouseEvent() to receive WM_MOUSELEAVE events).
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-06-08: Fixed ImGui_ImplWin32_EnableDpiAwareness() and ImGui_ImplWin32_GetDpiScaleForMonitor() to handle Windows 8.1/10 features without a manifest (per-monitor DPI, and properly calls SetProcessDpiAwareness() on 8.1).
// 2021-03-23: Inputs: Clearing keyboard down array when losing focus (WM_KILLFOCUS).
// 2021-02-18: Added ImGui_ImplWin32_EnableAlphaCompositing(). Non Visual Studio users will need to link with dwmapi.lib (MinGW/gcc: use -ldwmapi).
// 2021-02-17: Fixed ImGui_ImplWin32_EnableDpiAwareness() attempting to get SetProcessDpiAwareness from shcore.dll on Windows 8 whereas it is only supported on Windows 8.1.
// 2021-01-25: Inputs: Dynamically loading XInput DLL.
// 2020-12-04: Misc: Fixed setting of io.DisplaySize to invalid/uninitialized data when after hwnd has been closed.
// 2020-03-03: Inputs: Calling AddInputCharacterUTF16() to support surrogate pairs leading to codepoint >= 0x10000 (for more complete CJK inputs)
// 2020-02-17: Added ImGui_ImplWin32_EnableDpiAwareness(), ImGui_ImplWin32_GetDpiScaleForHwnd(), ImGui_ImplWin32_GetDpiScaleForMonitor() helper functions.
// 2020-01-14: Inputs: Added support for #define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD/IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT.
// 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor.
// 2019-05-11: Inputs: Don't filter value from WM_CHAR before calling AddInputCharacter().
// 2019-01-17: Misc: Using GetForegroundWindow()+IsChild() instead of GetActiveWindow() to be compatible with windows created in a different thread or parent.
// 2019-01-17: Inputs: Added support for mouse buttons 4 and 5 via WM_XBUTTON* messages.
// 2019-01-15: Inputs: Added support for XInput gamepads (if ImGuiConfigFlags_NavEnableGamepad is set by user application).
// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
// 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor.
// 2018-06-10: Inputs: Fixed handling of mouse wheel messages to support fine position messages (typically sent by track-pads).
// 2018-06-08: Misc: Extracted imgui_impl_win32.cpp/.h away from the old combined DX9/DX10/DX11/DX12 examples.
// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag.
// 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling).
// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
// 2018-02-06: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set).
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
// 2018-01-08: Inputs: Added mapping for ImGuiKey_Insert.
// 2018-01-05: Inputs: Added WM_LBUTTONDBLCLK double-click handlers for window classes with the CS_DBLCLKS flag.
// 2017-10-23: Inputs: Added WM_SYSKEYDOWN / WM_SYSKEYUP handlers so e.g. the VK_MENU key can be read.
// 2017-10-23: Inputs: Using Win32 ::SetCapture/::GetCapture() to retrieve mouse positions outside the client area when dragging.
// 2016-11-12: Inputs: Only call Win32 ::SetCursor(NULL) when io.MouseDrawCursor is set.
struct ImGui_ImplWin32_Data
{
HWND hWnd;
HWND MouseHwnd;
bool MouseTracked;
INT64 Time;
INT64 TicksPerSecond;
ImGuiMouseCursor LastMouseCursor;
bool HasGamepad;
bool WantUpdateHasGamepad;
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
HMODULE XInputDLL;
PFN_XInputGetCapabilities XInputGetCapabilities;
PFN_XInputGetState XInputGetState;
#endif
ImGui_ImplWin32_Data() { memset(this, 0, sizeof(*this)); }
};
// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
// FIXME: multi-context support is not well tested and probably dysfunctional in this backend.
// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context.
static ImGui_ImplWin32_Data* ImGui_ImplWin32_GetBackendData()
{
return ImGui::GetCurrentContext() ? (ImGui_ImplWin32_Data*)ImGui::GetIO().BackendPlatformUserData : NULL;
}
// Functions
bool ImGui_ImplWin32_Init(void* hwnd)
{
ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.BackendPlatformUserData == NULL && "Already initialized a platform backend!");
INT64 perf_frequency, perf_counter;
if (!::QueryPerformanceFrequency((LARGE_INTEGER*)&perf_frequency))
return false;
if (!::QueryPerformanceCounter((LARGE_INTEGER*)&perf_counter))
return false;
// Setup backend capabilities flags
ImGui_ImplWin32_Data* bd = IM_NEW(ImGui_ImplWin32_Data)();
io.BackendPlatformUserData = (void*)bd;
io.BackendPlatformName = "imgui_impl_win32";
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
bd->hWnd = (HWND)hwnd;
bd->WantUpdateHasGamepad = true;
bd->TicksPerSecond = perf_frequency;
bd->Time = perf_counter;
bd->LastMouseCursor = ImGuiMouseCursor_COUNT;
io.ImeWindowHandle = hwnd;
// Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array that we will update during the application lifetime.
io.KeyMap[ImGuiKey_Tab] = VK_TAB;
io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT;
io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;
io.KeyMap[ImGuiKey_UpArrow] = VK_UP;
io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN;
io.KeyMap[ImGuiKey_PageUp] = VK_PRIOR;
io.KeyMap[ImGuiKey_PageDown] = VK_NEXT;
io.KeyMap[ImGuiKey_Home] = VK_HOME;
io.KeyMap[ImGuiKey_End] = VK_END;
io.KeyMap[ImGuiKey_Insert] = VK_INSERT;
io.KeyMap[ImGuiKey_Delete] = VK_DELETE;
io.KeyMap[ImGuiKey_Backspace] = VK_BACK;
io.KeyMap[ImGuiKey_Space] = VK_SPACE;
io.KeyMap[ImGuiKey_Enter] = VK_RETURN;
io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE;
io.KeyMap[ImGuiKey_KeyPadEnter] = VK_RETURN;
io.KeyMap[ImGuiKey_A] = 'A';
io.KeyMap[ImGuiKey_C] = 'C';
io.KeyMap[ImGuiKey_V] = 'V';
io.KeyMap[ImGuiKey_X] = 'X';
io.KeyMap[ImGuiKey_Y] = 'Y';
io.KeyMap[ImGuiKey_Z] = 'Z';
// Dynamically load XInput library
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
const char* xinput_dll_names[] =
{
"xinput1_4.dll", // Windows 8+
"xinput1_3.dll", // DirectX SDK
"xinput9_1_0.dll", // Windows Vista, Windows 7
"xinput1_2.dll", // DirectX SDK
"xinput1_1.dll" // DirectX SDK
};
for (int n = 0; n < IM_ARRAYSIZE(xinput_dll_names); n++)
if (HMODULE dll = ::LoadLibraryA(xinput_dll_names[n]))
{
bd->XInputDLL = dll;
bd->XInputGetCapabilities = (PFN_XInputGetCapabilities)::GetProcAddress(dll, "XInputGetCapabilities");
bd->XInputGetState = (PFN_XInputGetState)::GetProcAddress(dll, "XInputGetState");
break;
}
#endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
return true;
}
void ImGui_ImplWin32_Shutdown()
{
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
IM_ASSERT(bd != NULL && "No platform backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
// Unload XInput library
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
if (bd->XInputDLL)
::FreeLibrary(bd->XInputDLL);
#endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
io.BackendPlatformName = NULL;
io.BackendPlatformUserData = NULL;
IM_DELETE(bd);
}
static bool ImGui_ImplWin32_UpdateMouseCursor()
{
ImGuiIO& io = ImGui::GetIO();
if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
return false;
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor)
{
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
::SetCursor(NULL);
}
else
{
// Show OS mouse cursor
LPTSTR win32_cursor = IDC_ARROW;
switch (imgui_cursor)
{
case ImGuiMouseCursor_Arrow: win32_cursor = IDC_ARROW; break;
case ImGuiMouseCursor_TextInput: win32_cursor = IDC_IBEAM; break;
case ImGuiMouseCursor_ResizeAll: win32_cursor = IDC_SIZEALL; break;
case ImGuiMouseCursor_ResizeEW: win32_cursor = IDC_SIZEWE; break;
case ImGuiMouseCursor_ResizeNS: win32_cursor = IDC_SIZENS; break;
case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break;
case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break;
case ImGuiMouseCursor_Hand: win32_cursor = IDC_HAND; break;
case ImGuiMouseCursor_NotAllowed: win32_cursor = IDC_NO; break;
}
::SetCursor(::LoadCursor(NULL, win32_cursor));
}
return true;
}
static void ImGui_ImplWin32_UpdateMousePos()
{
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(bd->hWnd != 0);
const ImVec2 mouse_pos_prev = io.MousePos;
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
// Obtain focused and hovered window. We forward mouse input when focused or when hovered (and no other window is capturing)
HWND focused_window = ::GetForegroundWindow();
HWND hovered_window = bd->MouseHwnd;
HWND mouse_window = NULL;
if (hovered_window && (hovered_window == bd->hWnd || ::IsChild(hovered_window, bd->hWnd)))
mouse_window = hovered_window;
else if (focused_window && (focused_window == bd->hWnd || ::IsChild(focused_window, bd->hWnd)))
mouse_window = focused_window;
if (mouse_window == NULL)
return;
// Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
if (io.WantSetMousePos)
{
POINT pos = { (int)mouse_pos_prev.x, (int)mouse_pos_prev.y };
if (::ClientToScreen(bd->hWnd, &pos))
::SetCursorPos(pos.x, pos.y);
}
// Set Dear ImGui mouse position from OS position
POINT pos;
if (::GetCursorPos(&pos) && ::ScreenToClient(mouse_window, &pos))
io.MousePos = ImVec2((float)pos.x, (float)pos.y);
}
// Gamepad navigation mapping
static void ImGui_ImplWin32_UpdateGamepads()
{
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
memset(io.NavInputs, 0, sizeof(io.NavInputs));
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
return;
// Calling XInputGetState() every frame on disconnected gamepads is unfortunately too slow.
// Instead we refresh gamepad availability by calling XInputGetCapabilities() _only_ after receiving WM_DEVICECHANGE.
if (bd->WantUpdateHasGamepad)
{
XINPUT_CAPABILITIES caps;
bd->HasGamepad = bd->XInputGetCapabilities ? (bd->XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS) : false;
bd->WantUpdateHasGamepad = false;
}
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
XINPUT_STATE xinput_state;
if (bd->HasGamepad && bd->XInputGetState && bd->XInputGetState(0, &xinput_state) == ERROR_SUCCESS)
{
const XINPUT_GAMEPAD& gamepad = xinput_state.Gamepad;
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
#define MAP_BUTTON(NAV_NO, BUTTON_ENUM) { io.NavInputs[NAV_NO] = (gamepad.wButtons & BUTTON_ENUM) ? 1.0f : 0.0f; }
#define MAP_ANALOG(NAV_NO, VALUE, V0, V1) { float vn = (float)(VALUE - V0) / (float)(V1 - V0); if (vn > 1.0f) vn = 1.0f; if (vn > 0.0f && io.NavInputs[NAV_NO] < vn) io.NavInputs[NAV_NO] = vn; }
MAP_BUTTON(ImGuiNavInput_Activate, XINPUT_GAMEPAD_A); // Cross / A
MAP_BUTTON(ImGuiNavInput_Cancel, XINPUT_GAMEPAD_B); // Circle / B
MAP_BUTTON(ImGuiNavInput_Menu, XINPUT_GAMEPAD_X); // Square / X
MAP_BUTTON(ImGuiNavInput_Input, XINPUT_GAMEPAD_Y); // Triangle / Y
MAP_BUTTON(ImGuiNavInput_DpadLeft, XINPUT_GAMEPAD_DPAD_LEFT); // D-Pad Left
MAP_BUTTON(ImGuiNavInput_DpadRight, XINPUT_GAMEPAD_DPAD_RIGHT); // D-Pad Right
MAP_BUTTON(ImGuiNavInput_DpadUp, XINPUT_GAMEPAD_DPAD_UP); // D-Pad Up
MAP_BUTTON(ImGuiNavInput_DpadDown, XINPUT_GAMEPAD_DPAD_DOWN); // D-Pad Down
MAP_BUTTON(ImGuiNavInput_FocusPrev, XINPUT_GAMEPAD_LEFT_SHOULDER); // L1 / LB
MAP_BUTTON(ImGuiNavInput_FocusNext, XINPUT_GAMEPAD_RIGHT_SHOULDER); // R1 / RB
MAP_BUTTON(ImGuiNavInput_TweakSlow, XINPUT_GAMEPAD_LEFT_SHOULDER); // L1 / LB
MAP_BUTTON(ImGuiNavInput_TweakFast, XINPUT_GAMEPAD_RIGHT_SHOULDER); // R1 / RB
MAP_ANALOG(ImGuiNavInput_LStickLeft, gamepad.sThumbLX, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768);
MAP_ANALOG(ImGuiNavInput_LStickRight, gamepad.sThumbLX, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767);
MAP_ANALOG(ImGuiNavInput_LStickUp, gamepad.sThumbLY, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767);
MAP_ANALOG(ImGuiNavInput_LStickDown, gamepad.sThumbLY, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32767);
#undef MAP_BUTTON
#undef MAP_ANALOG
}
#endif // #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
}
void ImGui_ImplWin32_NewFrame()
{
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
IM_ASSERT(bd != NULL && "Did you call ImGui_ImplWin32_Init()?");
// Setup display size (every frame to accommodate for window resizing)
RECT rect = { 0, 0, 0, 0 };
::GetClientRect(bd->hWnd, &rect);
io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top));
// Setup time step
INT64 current_time = 0;
::QueryPerformanceCounter((LARGE_INTEGER*)&current_time);
io.DeltaTime = (float)(current_time - bd->Time) / bd->TicksPerSecond;
bd->Time = current_time;
// Update OS mouse position
ImGui_ImplWin32_UpdateMousePos();
// Update OS mouse cursor with the cursor requested by imgui
ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor();
if (bd->LastMouseCursor != mouse_cursor)
{
bd->LastMouseCursor = mouse_cursor;
ImGui_ImplWin32_UpdateMouseCursor();
}
// Update game controllers (if enabled and available)
ImGui_ImplWin32_UpdateGamepads();
}
// Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WINNT/WINVER versions.
#ifndef WM_MOUSEHWHEEL
#define WM_MOUSEHWHEEL 0x020E
#endif
#ifndef DBT_DEVNODES_CHANGED
#define DBT_DEVNODES_CHANGED 0x0007
#endif
// Win32 message handler (process Win32 mouse/keyboard inputs, etc.)
// Call from your application's message handler.
// When implementing your own backend, you can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if Dear ImGui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
// Generally you may always pass all inputs to Dear ImGui, and hide them from your application based on those two flags.
// PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinates when dragging mouse outside of our window bounds.
// PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag.
#if 0
// Copy this line into your .cpp file to forward declare the function.
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
#endif
IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (ImGui::GetCurrentContext() == NULL)
return 0;
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
switch (msg)
{
case WM_MOUSEMOVE:
// We need to call TrackMouseEvent in order to receive WM_MOUSELEAVE events
bd->MouseHwnd = hwnd;
if (!bd->MouseTracked)
{
TRACKMOUSEEVENT tme = { sizeof(tme), TME_LEAVE, hwnd, 0 };
::TrackMouseEvent(&tme);
bd->MouseTracked = true;
}
break;
case WM_MOUSELEAVE:
if (bd->MouseHwnd == hwnd)
bd->MouseHwnd = NULL;
bd->MouseTracked = false;
break;
case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK:
case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK:
{
int button = 0;
if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) { button = 0; }
if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) { button = 1; }
if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) { button = 2; }
if (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONDBLCLK) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; }
if (!ImGui::IsAnyMouseDown() && ::GetCapture() == NULL)
::SetCapture(hwnd);
io.MouseDown[button] = true;
return 0;
}
case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
case WM_XBUTTONUP:
{
int button = 0;
if (msg == WM_LBUTTONUP) { button = 0; }
if (msg == WM_RBUTTONUP) { button = 1; }
if (msg == WM_MBUTTONUP) { button = 2; }
if (msg == WM_XBUTTONUP) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; }
io.MouseDown[button] = false;
if (!ImGui::IsAnyMouseDown() && ::GetCapture() == hwnd)
::ReleaseCapture();
return 0;
}
case WM_MOUSEWHEEL:
io.MouseWheel += (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA;
return 0;
case WM_MOUSEHWHEEL:
io.MouseWheelH += (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA;
return 0;
case WM_KEYDOWN:
case WM_KEYUP:
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
{
bool down = (msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN);
if (wParam < 256)
io.KeysDown[wParam] = down;
if (wParam == VK_CONTROL)
{
io.KeysDown[VK_LCONTROL] = ((::GetKeyState(VK_LCONTROL) & 0x8000) != 0);
io.KeysDown[VK_RCONTROL] = ((::GetKeyState(VK_RCONTROL) & 0x8000) != 0);
io.KeyCtrl = io.KeysDown[VK_LCONTROL] || io.KeysDown[VK_RCONTROL];
}
if (wParam == VK_SHIFT)
{
io.KeysDown[VK_LSHIFT] = ((::GetKeyState(VK_LSHIFT) & 0x8000) != 0);
io.KeysDown[VK_RSHIFT] = ((::GetKeyState(VK_RSHIFT) & 0x8000) != 0);
io.KeyShift = io.KeysDown[VK_LSHIFT] || io.KeysDown[VK_RSHIFT];
}
if (wParam == VK_MENU)
{
io.KeysDown[VK_LMENU] = ((::GetKeyState(VK_LMENU) & 0x8000) != 0);
io.KeysDown[VK_RMENU] = ((::GetKeyState(VK_RMENU) & 0x8000) != 0);
io.KeyAlt = io.KeysDown[VK_LMENU] || io.KeysDown[VK_RMENU];
}
return 0;
}
case WM_SETFOCUS:
case WM_KILLFOCUS:
io.AddFocusEvent(msg == WM_SETFOCUS);
return 0;
case WM_CHAR:
// You can also use ToAscii()+GetKeyboardState() to retrieve characters.
if (wParam > 0 && wParam < 0x10000)
io.AddInputCharacterUTF16((unsigned short)wParam);
return 0;
case WM_SETCURSOR:
if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor())
return 1;
return 0;
case WM_DEVICECHANGE:
if ((UINT)wParam == DBT_DEVNODES_CHANGED)
bd->WantUpdateHasGamepad = true;
return 0;
}
return 0;
}
//--------------------------------------------------------------------------------------------------------
// DPI-related helpers (optional)
//--------------------------------------------------------------------------------------------------------
// - Use to enable DPI awareness without having to create an application manifest.
// - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps.
// - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc.
// but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime,
// neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies.
//---------------------------------------------------------------------------------------------------------
// This is the scheme successfully used by GLFW (from which we borrowed some of the code) and other apps aiming to be highly portable.
// ImGui_ImplWin32_EnableDpiAwareness() is just a helper called by main.cpp, we don't call it automatically.
// If you are trying to implement your own backend for your own engine, you may ignore that noise.
//---------------------------------------------------------------------------------------------------------
// Perform our own check with RtlVerifyVersionInfo() instead of using functions from <VersionHelpers.h> as they
// require a manifest to be functional for checks above 8.1. See https://github.com/ocornut/imgui/issues/4200
static BOOL _IsWindowsVersionOrGreater(WORD major, WORD minor, WORD)
{
typedef LONG(WINAPI* PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*, ULONG, ULONGLONG);
static PFN_RtlVerifyVersionInfo RtlVerifyVersionInfoFn = NULL;
if (RtlVerifyVersionInfoFn == NULL)
if (HMODULE ntdllModule = ::GetModuleHandleA("ntdll.dll"))
RtlVerifyVersionInfoFn = (PFN_RtlVerifyVersionInfo)GetProcAddress(ntdllModule, "RtlVerifyVersionInfo");
if (RtlVerifyVersionInfoFn == NULL)
return FALSE;
RTL_OSVERSIONINFOEXW versionInfo = { };
ULONGLONG conditionMask = 0;
versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
versionInfo.dwMajorVersion = major;
versionInfo.dwMinorVersion = minor;
VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
return (RtlVerifyVersionInfoFn(&versionInfo, VER_MAJORVERSION | VER_MINORVERSION, conditionMask) == 0) ? TRUE : FALSE;
}
#define _IsWindowsVistaOrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0600), LOBYTE(0x0600), 0) // _WIN32_WINNT_VISTA
#define _IsWindows8OrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0602), LOBYTE(0x0602), 0) // _WIN32_WINNT_WIN8
#define _IsWindows8Point1OrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0603), LOBYTE(0x0603), 0) // _WIN32_WINNT_WINBLUE
#define _IsWindows10OrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0A00), LOBYTE(0x0A00), 0) // _WIN32_WINNT_WINTHRESHOLD / _WIN32_WINNT_WIN10
#ifndef DPI_ENUMS_DECLARED
typedef enum { PROCESS_DPI_UNAWARE = 0, PROCESS_SYSTEM_DPI_AWARE = 1, PROCESS_PER_MONITOR_DPI_AWARE = 2 } PROCESS_DPI_AWARENESS;
typedef enum { MDT_EFFECTIVE_DPI = 0, MDT_ANGULAR_DPI = 1, MDT_RAW_DPI = 2, MDT_DEFAULT = MDT_EFFECTIVE_DPI } MONITOR_DPI_TYPE;
#endif
#ifndef _DPI_AWARENESS_CONTEXTS_
DECLARE_HANDLE(DPI_AWARENESS_CONTEXT);
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE (DPI_AWARENESS_CONTEXT)-3
#endif
#ifndef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 (DPI_AWARENESS_CONTEXT)-4
#endif
typedef HRESULT(WINAPI* PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); // Shcore.lib + dll, Windows 8.1+
typedef HRESULT(WINAPI* PFN_GetDpiForMonitor)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*); // Shcore.lib + dll, Windows 8.1+
typedef DPI_AWARENESS_CONTEXT(WINAPI* PFN_SetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT); // User32.lib + dll, Windows 10 v1607+ (Creators Update)
// Helper function to enable DPI awareness without setting up a manifest
void ImGui_ImplWin32_EnableDpiAwareness()
{
if (_IsWindows10OrGreater())
{
static HINSTANCE user32_dll = ::LoadLibraryA("user32.dll"); // Reference counted per-process
if (PFN_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContextFn = (PFN_SetThreadDpiAwarenessContext)::GetProcAddress(user32_dll, "SetThreadDpiAwarenessContext"))
{
SetThreadDpiAwarenessContextFn(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
return;
}
}
if (_IsWindows8Point1OrGreater())
{
static HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll"); // Reference counted per-process
if (PFN_SetProcessDpiAwareness SetProcessDpiAwarenessFn = (PFN_SetProcessDpiAwareness)::GetProcAddress(shcore_dll, "SetProcessDpiAwareness"))
{
SetProcessDpiAwarenessFn(PROCESS_PER_MONITOR_DPI_AWARE);
return;
}
}
#if _WIN32_WINNT >= 0x0600
::SetProcessDPIAware();
#endif
}
#if defined(_MSC_VER) && !defined(NOGDI)
#pragma comment(lib, "gdi32") // Link with gdi32.lib for GetDeviceCaps(). MinGW will require linking with '-lgdi32'
#endif
float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor)
{
UINT xdpi = 96, ydpi = 96;
if (_IsWindows8Point1OrGreater())
{
static HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll"); // Reference counted per-process
static PFN_GetDpiForMonitor GetDpiForMonitorFn = NULL;
if (GetDpiForMonitorFn == NULL && shcore_dll != NULL)
GetDpiForMonitorFn = (PFN_GetDpiForMonitor)::GetProcAddress(shcore_dll, "GetDpiForMonitor");
if (GetDpiForMonitorFn != NULL)
{
GetDpiForMonitorFn((HMONITOR)monitor, MDT_EFFECTIVE_DPI, &xdpi, &ydpi);
IM_ASSERT(xdpi == ydpi); // Please contact me if you hit this assert!
return xdpi / 96.0f;
}
}
#ifndef NOGDI
const HDC dc = ::GetDC(NULL);
xdpi = ::GetDeviceCaps(dc, LOGPIXELSX);
ydpi = ::GetDeviceCaps(dc, LOGPIXELSY);
IM_ASSERT(xdpi == ydpi); // Please contact me if you hit this assert!
::ReleaseDC(NULL, dc);
#endif
return xdpi / 96.0f;
}
float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd)
{
HMONITOR monitor = ::MonitorFromWindow((HWND)hwnd, MONITOR_DEFAULTTONEAREST);
return ImGui_ImplWin32_GetDpiScaleForMonitor(monitor);
}
//---------------------------------------------------------------------------------------------------------
// Transparency related helpers (optional)
//--------------------------------------------------------------------------------------------------------
#if defined(_MSC_VER)
#pragma comment(lib, "dwmapi") // Link with dwmapi.lib. MinGW will require linking with '-ldwmapi'
#endif
// [experimental]
// Borrowed from GLFW's function updateFramebufferTransparency() in src/win32_window.c
// (the Dwm* functions are Vista era functions but we are borrowing logic from GLFW)
void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd)
{
if (!_IsWindowsVistaOrGreater())
return;
BOOL composition;
if (FAILED(::DwmIsCompositionEnabled(&composition)) || !composition)
return;
BOOL opaque;
DWORD color;
if (_IsWindows8OrGreater() || (SUCCEEDED(::DwmGetColorizationColor(&color, &opaque)) && !opaque))
{
HRGN region = ::CreateRectRgn(0, 0, -1, -1);
DWM_BLURBEHIND bb = {};
bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
bb.hRgnBlur = region;
bb.fEnable = TRUE;
::DwmEnableBlurBehindWindow((HWND)hwnd, &bb);
::DeleteObject(region);
}
else
{
DWM_BLURBEHIND bb = {};
bb.dwFlags = DWM_BB_ENABLE;
::DwmEnableBlurBehindWindow((HWND)hwnd, &bb);
}
}
//---------------------------------------------------------------------------------------------------------

View File

@@ -0,0 +1,42 @@
// dear imgui: Platform Backend for Windows (standard windows API for 32 and 64 bits applications)
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
// Implemented features:
// [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui)
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE).
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
#pragma once
#include "imgui.h" // IMGUI_IMPL_API
IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd);
IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown();
IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame();
// Win32 message handler your application need to call.
// - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on <windows.h> from this helper.
// - You should COPY the line below into your .cpp code to forward declare the function and then you can call it.
#if 0
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
#endif
// DPI-related helpers (optional)
// - Use to enable DPI awareness without having to create an application manifest.
// - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps.
// - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc.
// but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime,
// neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies.
IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness();
IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd
IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor
// Transparency related helpers (optional) [experimental]
// - Use to enable alpha compositing transparency with the desktop.
// - Use together with e.g. clearing your framebuffer with zero-alpha.
IMGUI_IMPL_API void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd); // HWND hwnd

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,72 @@
// dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.)
// This is also an example of how you may wrap your own similar types.
// Changelog:
// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string
#include "imgui.h"
#include "imgui_stdlib.h"
struct InputTextCallback_UserData
{
std::string* Str;
ImGuiInputTextCallback ChainCallback;
void* ChainCallbackUserData;
};
static int InputTextCallback(ImGuiInputTextCallbackData* data)
{
InputTextCallback_UserData* user_data = (InputTextCallback_UserData*)data->UserData;
if (data->EventFlag == ImGuiInputTextFlags_CallbackResize)
{
// Resize string callback
// If for some reason we refuse the new length (BufTextLen) and/or capacity (BufSize) we need to set them back to what we want.
std::string* str = user_data->Str;
IM_ASSERT(data->Buf == str->c_str());
str->resize(data->BufTextLen);
data->Buf = (char*)str->c_str();
}
else if (user_data->ChainCallback)
{
// Forward to user callback, if any
data->UserData = user_data->ChainCallbackUserData;
return user_data->ChainCallback(data);
}
return 0;
}
bool ImGui::InputText(const char* label, std::string* str, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
{
IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
flags |= ImGuiInputTextFlags_CallbackResize;
InputTextCallback_UserData cb_user_data;
cb_user_data.Str = str;
cb_user_data.ChainCallback = callback;
cb_user_data.ChainCallbackUserData = user_data;
return InputText(label, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data);
}
bool ImGui::InputTextMultiline(const char* label, std::string* str, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
{
IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
flags |= ImGuiInputTextFlags_CallbackResize;
InputTextCallback_UserData cb_user_data;
cb_user_data.Str = str;
cb_user_data.ChainCallback = callback;
cb_user_data.ChainCallbackUserData = user_data;
return InputTextMultiline(label, (char*)str->c_str(), str->capacity() + 1, size, flags, InputTextCallback, &cb_user_data);
}
bool ImGui::InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
{
IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
flags |= ImGuiInputTextFlags_CallbackResize;
InputTextCallback_UserData cb_user_data;
cb_user_data.Str = str;
cb_user_data.ChainCallback = callback;
cb_user_data.ChainCallbackUserData = user_data;
return InputTextWithHint(label, hint, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data);
}

View File

@@ -0,0 +1,18 @@
// dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.)
// This is also an example of how you may wrap your own similar types.
// Changelog:
// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string
#pragma once
#include <string>
namespace ImGui
{
// ImGui::InputText() with std::string
// Because text input needs dynamic resizing, we need to setup a callback to grow the capacity
IMGUI_API bool InputText(const char* label, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
IMGUI_API bool InputTextMultiline(const char* label, std::string* str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
IMGUI_API bool InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,639 @@
// [DEAR IMGUI]
// This is a slightly modified version of stb_rect_pack.h 1.00.
// Those changes would need to be pushed into nothings/stb:
// - Added STBRP__CDECL
// Grep for [DEAR IMGUI] to find the changes.
// stb_rect_pack.h - v1.00 - public domain - rectangle packing
// Sean Barrett 2014
//
// Useful for e.g. packing rectangular textures into an atlas.
// Does not do rotation.
//
// Not necessarily the awesomest packing method, but better than
// the totally naive one in stb_truetype (which is primarily what
// this is meant to replace).
//
// Has only had a few tests run, may have issues.
//
// More docs to come.
//
// No memory allocations; uses qsort() and assert() from stdlib.
// Can override those by defining STBRP_SORT and STBRP_ASSERT.
//
// This library currently uses the Skyline Bottom-Left algorithm.
//
// Please note: better rectangle packers are welcome! Please
// implement them to the same API, but with a different init
// function.
//
// Credits
//
// Library
// Sean Barrett
// Minor features
// Martins Mozeiko
// github:IntellectualKitty
//
// Bugfixes / warning fixes
// Jeremy Jaussaud
// Fabian Giesen
//
// Version history:
//
// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
// 0.99 (2019-02-07) warning fixes
// 0.11 (2017-03-03) return packing success/fail result
// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
// 0.09 (2016-08-27) fix compiler warnings
// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0)
// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0)
// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
// 0.05: added STBRP_ASSERT to allow replacing assert
// 0.04: fixed minor bug in STBRP_LARGE_RECTS support
// 0.01: initial release
//
// LICENSE
//
// See end of file for license information.
//////////////////////////////////////////////////////////////////////////////
//
// INCLUDE SECTION
//
#ifndef STB_INCLUDE_STB_RECT_PACK_H
#define STB_INCLUDE_STB_RECT_PACK_H
#define STB_RECT_PACK_VERSION 1
#ifdef STBRP_STATIC
#define STBRP_DEF static
#else
#define STBRP_DEF extern
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef struct stbrp_context stbrp_context;
typedef struct stbrp_node stbrp_node;
typedef struct stbrp_rect stbrp_rect;
#ifdef STBRP_LARGE_RECTS
typedef int stbrp_coord;
#else
typedef unsigned short stbrp_coord;
#endif
STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
// Assign packed locations to rectangles. The rectangles are of type
// 'stbrp_rect' defined below, stored in the array 'rects', and there
// are 'num_rects' many of them.
//
// Rectangles which are successfully packed have the 'was_packed' flag
// set to a non-zero value and 'x' and 'y' store the minimum location
// on each axis (i.e. bottom-left in cartesian coordinates, top-left
// if you imagine y increasing downwards). Rectangles which do not fit
// have the 'was_packed' flag set to 0.
//
// You should not try to access the 'rects' array from another thread
// while this function is running, as the function temporarily reorders
// the array while it executes.
//
// To pack into another rectangle, you need to call stbrp_init_target
// again. To continue packing into the same rectangle, you can call
// this function again. Calling this multiple times with multiple rect
// arrays will probably produce worse packing results than calling it
// a single time with the full rectangle array, but the option is
// available.
//
// The function returns 1 if all of the rectangles were successfully
// packed and 0 otherwise.
struct stbrp_rect
{
// reserved for your use:
int id;
// input:
stbrp_coord w, h;
// output:
stbrp_coord x, y;
int was_packed; // non-zero if valid packing
}; // 16 bytes, nominally
STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
// Initialize a rectangle packer to:
// pack a rectangle that is 'width' by 'height' in dimensions
// using temporary storage provided by the array 'nodes', which is 'num_nodes' long
//
// You must call this function every time you start packing into a new target.
//
// There is no "shutdown" function. The 'nodes' memory must stay valid for
// the following stbrp_pack_rects() call (or calls), but can be freed after
// the call (or calls) finish.
//
// Note: to guarantee best results, either:
// 1. make sure 'num_nodes' >= 'width'
// or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1'
//
// If you don't do either of the above things, widths will be quantized to multiples
// of small integers to guarantee the algorithm doesn't run out of temporary storage.
//
// If you do #2, then the non-quantized algorithm will be used, but the algorithm
// may run out of temporary storage and be unable to pack some rectangles.
STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
// Optionally call this function after init but before doing any packing to
// change the handling of the out-of-temp-memory scenario, described above.
// If you call init again, this will be reset to the default (false).
STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
// Optionally select which packing heuristic the library should use. Different
// heuristics will produce better/worse results for different data sets.
// If you call init again, this will be reset to the default.
enum
{
STBRP_HEURISTIC_Skyline_default=0,
STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
STBRP_HEURISTIC_Skyline_BF_sortHeight
};
//////////////////////////////////////////////////////////////////////////////
//
// the details of the following structures don't matter to you, but they must
// be visible so you can handle the memory allocations for them
struct stbrp_node
{
stbrp_coord x,y;
stbrp_node *next;
};
struct stbrp_context
{
int width;
int height;
int align;
int init_mode;
int heuristic;
int num_nodes;
stbrp_node *active_head;
stbrp_node *free_head;
stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2'
};
#ifdef __cplusplus
}
#endif
#endif
//////////////////////////////////////////////////////////////////////////////
//
// IMPLEMENTATION SECTION
//
#ifdef STB_RECT_PACK_IMPLEMENTATION
#ifndef STBRP_SORT
#include <stdlib.h>
#define STBRP_SORT qsort
#endif
#ifndef STBRP_ASSERT
#include <assert.h>
#define STBRP_ASSERT assert
#endif
// [DEAR IMGUI] Added STBRP__CDECL
#ifdef _MSC_VER
#define STBRP__NOTUSED(v) (void)(v)
#define STBRP__CDECL __cdecl
#else
#define STBRP__NOTUSED(v) (void)sizeof(v)
#define STBRP__CDECL
#endif
enum
{
STBRP__INIT_skyline = 1
};
STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
{
switch (context->init_mode) {
case STBRP__INIT_skyline:
STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
context->heuristic = heuristic;
break;
default:
STBRP_ASSERT(0);
}
}
STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
{
if (allow_out_of_mem)
// if it's ok to run out of memory, then don't bother aligning them;
// this gives better packing, but may fail due to OOM (even though
// the rectangles easily fit). @TODO a smarter approach would be to only
// quantize once we've hit OOM, then we could get rid of this parameter.
context->align = 1;
else {
// if it's not ok to run out of memory, then quantize the widths
// so that num_nodes is always enough nodes.
//
// I.e. num_nodes * align >= width
// align >= width / num_nodes
// align = ceil(width/num_nodes)
context->align = (context->width + context->num_nodes-1) / context->num_nodes;
}
}
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
{
int i;
#ifndef STBRP_LARGE_RECTS
STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
#endif
for (i=0; i < num_nodes-1; ++i)
nodes[i].next = &nodes[i+1];
nodes[i].next = NULL;
context->init_mode = STBRP__INIT_skyline;
context->heuristic = STBRP_HEURISTIC_Skyline_default;
context->free_head = &nodes[0];
context->active_head = &context->extra[0];
context->width = width;
context->height = height;
context->num_nodes = num_nodes;
stbrp_setup_allow_out_of_mem(context, 0);
// node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly)
context->extra[0].x = 0;
context->extra[0].y = 0;
context->extra[0].next = &context->extra[1];
context->extra[1].x = (stbrp_coord) width;
#ifdef STBRP_LARGE_RECTS
context->extra[1].y = (1<<30);
#else
context->extra[1].y = 65535;
#endif
context->extra[1].next = NULL;
}
// find minimum y position if it starts at x1
static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
{
stbrp_node *node = first;
int x1 = x0 + width;
int min_y, visited_width, waste_area;
STBRP__NOTUSED(c);
STBRP_ASSERT(first->x <= x0);
#if 0
// skip in case we're past the node
while (node->next->x <= x0)
++node;
#else
STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency
#endif
STBRP_ASSERT(node->x <= x0);
min_y = 0;
waste_area = 0;
visited_width = 0;
while (node->x < x1) {
if (node->y > min_y) {
// raise min_y higher.
// we've accounted for all waste up to min_y,
// but we'll now add more waste for everything we've visted
waste_area += visited_width * (node->y - min_y);
min_y = node->y;
// the first time through, visited_width might be reduced
if (node->x < x0)
visited_width += node->next->x - x0;
else
visited_width += node->next->x - node->x;
} else {
// add waste area
int under_width = node->next->x - node->x;
if (under_width + visited_width > width)
under_width = width - visited_width;
waste_area += under_width * (min_y - node->y);
visited_width += under_width;
}
node = node->next;
}
*pwaste = waste_area;
return min_y;
}
typedef struct
{
int x,y;
stbrp_node **prev_link;
} stbrp__findresult;
static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
{
int best_waste = (1<<30), best_x, best_y = (1 << 30);
stbrp__findresult fr;
stbrp_node **prev, *node, *tail, **best = NULL;
// align to multiple of c->align
width = (width + c->align - 1);
width -= width % c->align;
STBRP_ASSERT(width % c->align == 0);
// if it can't possibly fit, bail immediately
if (width > c->width || height > c->height) {
fr.prev_link = NULL;
fr.x = fr.y = 0;
return fr;
}
node = c->active_head;
prev = &c->active_head;
while (node->x + width <= c->width) {
int y,waste;
y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL
// bottom left
if (y < best_y) {
best_y = y;
best = prev;
}
} else {
// best-fit
if (y + height <= c->height) {
// can only use it if it first vertically
if (y < best_y || (y == best_y && waste < best_waste)) {
best_y = y;
best_waste = waste;
best = prev;
}
}
}
prev = &node->next;
node = node->next;
}
best_x = (best == NULL) ? 0 : (*best)->x;
// if doing best-fit (BF), we also have to try aligning right edge to each node position
//
// e.g, if fitting
//
// ____________________
// |____________________|
//
// into
//
// | |
// | ____________|
// |____________|
//
// then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned
//
// This makes BF take about 2x the time
if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
tail = c->active_head;
node = c->active_head;
prev = &c->active_head;
// find first node that's admissible
while (tail->x < width)
tail = tail->next;
while (tail) {
int xpos = tail->x - width;
int y,waste;
STBRP_ASSERT(xpos >= 0);
// find the left position that matches this
while (node->next->x <= xpos) {
prev = &node->next;
node = node->next;
}
STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
if (y + height <= c->height) {
if (y <= best_y) {
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
best_x = xpos;
STBRP_ASSERT(y <= best_y);
best_y = y;
best_waste = waste;
best = prev;
}
}
}
tail = tail->next;
}
}
fr.prev_link = best;
fr.x = best_x;
fr.y = best_y;
return fr;
}
static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
{
// find best position according to heuristic
stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
stbrp_node *node, *cur;
// bail if:
// 1. it failed
// 2. the best node doesn't fit (we don't always check this)
// 3. we're out of memory
if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
res.prev_link = NULL;
return res;
}
// on success, create new node
node = context->free_head;
node->x = (stbrp_coord) res.x;
node->y = (stbrp_coord) (res.y + height);
context->free_head = node->next;
// insert the new node into the right starting point, and
// let 'cur' point to the remaining nodes needing to be
// stiched back in
cur = *res.prev_link;
if (cur->x < res.x) {
// preserve the existing one, so start testing with the next one
stbrp_node *next = cur->next;
cur->next = node;
cur = next;
} else {
*res.prev_link = node;
}
// from here, traverse cur and free the nodes, until we get to one
// that shouldn't be freed
while (cur->next && cur->next->x <= res.x + width) {
stbrp_node *next = cur->next;
// move the current node to the free list
cur->next = context->free_head;
context->free_head = cur;
cur = next;
}
// stitch the list back in
node->next = cur;
if (cur->x < res.x + width)
cur->x = (stbrp_coord) (res.x + width);
#ifdef _DEBUG
cur = context->active_head;
while (cur->x < context->width) {
STBRP_ASSERT(cur->x < cur->next->x);
cur = cur->next;
}
STBRP_ASSERT(cur->next == NULL);
{
int count=0;
cur = context->active_head;
while (cur) {
cur = cur->next;
++count;
}
cur = context->free_head;
while (cur) {
cur = cur->next;
++count;
}
STBRP_ASSERT(count == context->num_nodes+2);
}
#endif
return res;
}
// [DEAR IMGUI] Added STBRP__CDECL
static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
{
const stbrp_rect *p = (const stbrp_rect *) a;
const stbrp_rect *q = (const stbrp_rect *) b;
if (p->h > q->h)
return -1;
if (p->h < q->h)
return 1;
return (p->w > q->w) ? -1 : (p->w < q->w);
}
// [DEAR IMGUI] Added STBRP__CDECL
static int STBRP__CDECL rect_original_order(const void *a, const void *b)
{
const stbrp_rect *p = (const stbrp_rect *) a;
const stbrp_rect *q = (const stbrp_rect *) b;
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
}
#ifdef STBRP_LARGE_RECTS
#define STBRP__MAXVAL 0xffffffff
#else
#define STBRP__MAXVAL 0xffff
#endif
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
{
int i, all_rects_packed = 1;
// we use the 'was_packed' field internally to allow sorting/unsorting
for (i=0; i < num_rects; ++i) {
rects[i].was_packed = i;
}
// sort according to heuristic
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
for (i=0; i < num_rects; ++i) {
if (rects[i].w == 0 || rects[i].h == 0) {
rects[i].x = rects[i].y = 0; // empty rect needs no space
} else {
stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
if (fr.prev_link) {
rects[i].x = (stbrp_coord) fr.x;
rects[i].y = (stbrp_coord) fr.y;
} else {
rects[i].x = rects[i].y = STBRP__MAXVAL;
}
}
}
// unsort
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
// set was_packed flags and all_rects_packed status
for (i=0; i < num_rects; ++i) {
rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
if (!rects[i].was_packed)
all_rects_packed = 0;
}
// return the all_rects_packed status
return all_rects_packed;
}
#endif
/*
------------------------------------------------------------------------------
This software is available under 2 licenses -- choose whichever you prefer.
------------------------------------------------------------------------------
ALTERNATIVE A - MIT License
Copyright (c) 2017 Sean Barrett
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------------------------------
*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Fichiers sources">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Fichiers d%27en-tête">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Fichiers de ressources">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="pch.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="Memory\sigscan.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="Utils\Output\Output.hpp">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="Hooks\Hooks.hpp">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="Features\Menu.hpp">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="Dependencies\imgui\imconfig.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="Dependencies\imgui\imgui_impl_dx11.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="Dependencies\imgui\imgui_impl_win32.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="Dependencies\imgui\imgui_internal.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="Dependencies\imgui\imstb_rectpack.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="Dependencies\imgui\imstb_textedit.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="Dependencies\imgui\imstb_truetype.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="dllmain.hpp">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="Dependencies\imgui\imgui.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
<ClInclude Include="Dependencies\imgui\imgui_impl_metal.h">
<Filter>Fichiers d%27en-tête</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="pch.cpp">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="Utils\Output\Output.cpp">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="Hooks\Hooks.cpp">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="Features\Menu.cpp">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="Dependencies\imgui\imgui_draw.cpp">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="Dependencies\imgui\imgui_impl_win32.cpp">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="Dependencies\imgui\imgui_widgets.cpp">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="Dependencies\imgui\imgui.cpp">
<Filter>Fichiers sources</Filter>
</ClCompile>
<ClCompile Include="Dependencies\imgui\imgui_tables.cpp">
<Filter>Fichiers sources</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ShowAllFiles>true</ShowAllFiles>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,366 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{c7cbebbd-cef6-40c5-b6f5-2098545bb8a5}</ProjectGuid>
<RootNamespace>DevourClient</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Include;$(SolutionDir)DevourClient\Dependencies;$(IncludePath)</IncludePath>
<LibraryPath>C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Lib\x86;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Include;$(SolutionDir)DevourClient\Dependencies\Minhook\include;$(SolutionDir)DevourClient\Dependencies;$(IncludePath)</IncludePath>
<LibraryPath>C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Lib\x64;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Include;$(SolutionDir)DevourClient\Dependencies;$(IncludePath)</IncludePath>
<LibraryPath>C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Lib\x86;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Include;$(SolutionDir)DevourClient\Dependencies\Minhook\include;$(SolutionDir)DevourClient\Dependencies;$(IncludePath)</IncludePath>
<LibraryPath>C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Lib\x64;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<VcpkgUseStatic>false</VcpkgUseStatic>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Vcpkg">
<VcpkgUseStatic>false</VcpkgUseStatic>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<VcpkgUseStatic>false</VcpkgUseStatic>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Vcpkg">
<VcpkgUseStatic>false</VcpkgUseStatic>
</PropertyGroup>
<PropertyGroup Label="Vcpkg">
<VcpkgEnabled>false</VcpkgEnabled>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;DLL1_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalOptions>/NODEFAULTLIB:LIBCMT /NODEFAULTLIB:LIBCMTD %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;DLL1_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalOptions>/NODEFAULTLIB:LIBCMT /NODEFAULTLIB:LIBCMTD %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;DLL1_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalOptions>/NODEFAULTLIB:LIBCMT /NODEFAULTLIB:LIBCMTD %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;DLL1_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalOptions>/NODEFAULTLIB:LIBCMT /NODEFAULTLIB:LIBCMTD %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(SolutionDir)include;</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalOptions>/NODEFAULTLIB:LIBCMT /NODEFAULTLIB:LIBCMTD %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>$(SolutionDir)include;</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalOptions>/NODEFAULTLIB:LIBCMT /NODEFAULTLIB:LIBCMTD %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="Dependencies\IL2CPP_Resolver\Cache.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Data.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Defines.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Functions\Callback.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Functions\Class.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Functions\Domain.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Functions\ResolveCall.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Functions\String.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Functions\Thread.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Includes.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\il2cpp_resolver.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Unity\API\Camera.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Unity\API\Component.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Unity\API\GameObject.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Unity\API\LayerMask.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Unity\API\Object.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Unity\API\Rigidbody.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Unity\API\Transform.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Unity\API\_TEMPLATE_API.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Unity\Defines.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Unity\Includes.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Unity\Obfuscators.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Unity\Structures\Engine.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Unity\Structures\il2cpp.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Unity\Structures\il2cppArray.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Unity\Structures\il2cppDictionary.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Unity\Structures\Includes.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Unity\Structures\System_String.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Utils\Helper.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Utils\Joaat.hpp" />
<ClInclude Include="Dependencies\IL2CPP_Resolver\Utils\VFunc.hpp" />
<ClInclude Include="Dependencies\imgui\imconfig.h" />
<ClInclude Include="Dependencies\imgui\imgui.h" />
<ClInclude Include="Dependencies\imgui\imgui_impl_dx11.h" />
<ClInclude Include="Dependencies\imgui\imgui_impl_metal.h" />
<ClInclude Include="Dependencies\imgui\imgui_impl_win32.h" />
<ClInclude Include="Dependencies\imgui\imgui_internal.h" />
<ClInclude Include="Dependencies\imgui\imgui_stdlib.h" />
<ClInclude Include="Dependencies\imgui\imstb_rectpack.h" />
<ClInclude Include="Dependencies\imgui\imstb_textedit.h" />
<ClInclude Include="Dependencies\imgui\imstb_truetype.h" />
<ClInclude Include="Dependencies\Minhook\include\MinHook.h" />
<ClInclude Include="Dependencies\Minhook\src\buffer.h" />
<ClInclude Include="Dependencies\Minhook\src\HDE\hde32.h" />
<ClInclude Include="Dependencies\Minhook\src\HDE\hde64.h" />
<ClInclude Include="Dependencies\Minhook\src\HDE\pstdint.h" />
<ClInclude Include="Dependencies\Minhook\src\HDE\table32.h" />
<ClInclude Include="Dependencies\Minhook\src\HDE\table64.h" />
<ClInclude Include="Dependencies\Minhook\src\trampoline.h" />
<ClInclude Include="dllmain.hpp" />
<ClInclude Include="Features\Menu.hpp" />
<ClInclude Include="Features\Misc\Misc.hpp" />
<ClInclude Include="framework.h" />
<ClInclude Include="Hooks\Hooks.hpp" />
<ClInclude Include="pch.h" />
<ClInclude Include="Callbacks\OnUpdate.hpp" />
<ClInclude Include="Utils\Dumper\Dumper.hpp" />
<ClInclude Include="Utils\Output\Output.hpp" />
<ClInclude Include="Utils\Players\Players.hpp" />
<ClInclude Include="Utils\Settings\Settings.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="Dependencies\IL2CPP_Resolver\Cache.cpp" />
<ClCompile Include="Dependencies\IL2CPP_Resolver\Data.cpp" />
<ClCompile Include="Dependencies\IL2CPP_Resolver\Functions\Callback.cpp" />
<ClCompile Include="Dependencies\IL2CPP_Resolver\Functions\Class.cpp" />
<ClCompile Include="Dependencies\IL2CPP_Resolver\Functions\String.cpp" />
<ClCompile Include="Dependencies\IL2CPP_Resolver\Functions\Thread.cpp" />
<ClCompile Include="Dependencies\IL2CPP_Resolver\il2cpp_resolver.cpp" />
<ClCompile Include="Dependencies\IL2CPP_Resolver\Unity\API\Camera.cpp" />
<ClCompile Include="Dependencies\IL2CPP_Resolver\Unity\API\Component.cpp" />
<ClCompile Include="Dependencies\IL2CPP_Resolver\Unity\API\GameObject.cpp" />
<ClCompile Include="Dependencies\IL2CPP_Resolver\Unity\API\LayerMask.cpp" />
<ClCompile Include="Dependencies\IL2CPP_Resolver\Unity\API\Object.cpp" />
<ClCompile Include="Dependencies\IL2CPP_Resolver\Unity\API\Rigidbody.cpp" />
<ClCompile Include="Dependencies\IL2CPP_Resolver\Unity\API\Transform.cpp" />
<ClCompile Include="Dependencies\IL2CPP_Resolver\Unity\API\_TEMPLATE_API.cpp" />
<ClCompile Include="Dependencies\IL2CPP_Resolver\Unity\Obfuscators.cpp" />
<ClCompile Include="Dependencies\IL2CPP_Resolver\Utils\Helper.cpp" />
<ClCompile Include="Dependencies\imgui\imgui.cpp" />
<ClCompile Include="Dependencies\imgui\imgui_draw.cpp" />
<ClCompile Include="Dependencies\imgui\imgui_impl_dx11.cpp" />
<ClCompile Include="Dependencies\imgui\imgui_impl_win32.cpp" />
<ClCompile Include="Dependencies\imgui\imgui_stdlib.cpp" />
<ClCompile Include="Dependencies\imgui\imgui_tables.cpp" />
<ClCompile Include="Dependencies\imgui\imgui_widgets.cpp" />
<ClCompile Include="Dependencies\Minhook\src\buffer.c" />
<ClCompile Include="Dependencies\Minhook\src\HDE\hde32.c" />
<ClCompile Include="Dependencies\Minhook\src\HDE\hde64.c" />
<ClCompile Include="Dependencies\Minhook\src\hook.c" />
<ClCompile Include="Dependencies\Minhook\src\trampoline.c" />
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="Features\Menu.cpp" />
<ClCompile Include="Features\Misc\Misc.cpp" />
<ClCompile Include="Hooks\Hooks.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="Callbacks\OnUpdate.cpp" />
<ClCompile Include="Utils\Dumper\Dumper.cpp" />
<ClCompile Include="Utils\Output\Output.cpp" />
<ClCompile Include="Utils\Players\Players.cpp" />
<ClCompile Include="Utils\Settings\Settings.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ShowAllFiles>true</ShowAllFiles>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,281 @@
#include "Menu.hpp"
#include "../Utils/Output/Output.hpp"
#include "../dllmain.hpp"
#include "../Utils/Settings/Settings.hpp"
#include "../Utils/Dumper/Dumper.hpp"
#include <string>
void InitStyle()
{
ImGui::StyleColorsDark();
auto& Style = ImGui::GetStyle();
Style.WindowRounding = 8.000f;
Style.FrameRounding = 4.000f;
Style.Colors[ImGuiCol_WindowBg] = ImColor(0, 0, 0, 240);
Style.Colors[ImGuiCol_TitleBg] = ImColor(1, 1, 1, 240);
Style.Colors[ImGuiCol_TitleBgActive] = ImColor(1, 1, 1, 240);
Style.Colors[ImGuiCol_TitleBgCollapsed] = ImColor(0, 0, 0, 240);
Style.Colors[ImGuiCol_Button] = ImColor(46, 53, 62, 20);
Style.Colors[ImGuiCol_ButtonHovered] = ImColor(46, 53, 62, 255);
Style.Colors[ImGuiCol_ButtonActive] = ImColor(46, 53, 62, 255);
Style.Colors[ImGuiCol_CheckMark] = ImColor(183, 185, 189, 255);
Style.Colors[ImGuiCol_FrameBg] = ImColor(60, 66, 76, 138);
Style.Colors[ImGuiCol_FrameBgActive] = ImColor(60, 66, 76, 171);
Style.Colors[ImGuiCol_FrameBgHovered] = ImColor(60, 66, 76, 102);
Style.Alpha = 0.8f;
ImGuiIO& io = ImGui::GetIO();
io.Fonts->AddFontFromFileTTF("C:\\Windows\\Fonts\\tahoma.ttf", 13.000f);
}
void DrawVisualsTab() {
ImGui::Checkbox("Big flashlight", &settings::big_flashlight);
bool open_flcolor_popup = ImGui::ColorButton("flashlightcolor", ImVec4(settings::flashlight_color[0], settings::flashlight_color[1], settings::flashlight_color[2], settings::flashlight_color[3]));
if (open_flcolor_popup)
{
ImGui::OpenPopup("flashlightcolorpicker");
}
if (ImGui::BeginPopup("flashlightcolorpicker")) {
ImGui::ColorPicker4("Flashlight color", (float*)&settings::flashlight_color);
ImGui::EndPopup();
}
ImGui::SameLine();
ImGui::Text("Flashlight color");
ImGui::Checkbox("Unlimited UV", &settings::unlimited_uv);
ImGui::Checkbox("Fullbright", &settings::fullbright);
ImGui::Checkbox("Player ESP", &settings::player_esp);
ImGui::SameLine();
bool open_pelcolor_popup = ImGui::ColorButton("playerespcolor", ImVec4(settings::player_esp_color[0], settings::player_esp_color[1], settings::player_esp_color[2], settings::player_esp_color[3]));
if (open_pelcolor_popup)
{
ImGui::OpenPopup("playeresppop");
}
if (ImGui::BeginPopup("playeresppop")) {
ImGui::ColorPicker4("Player ESP color", (float*)&settings::player_esp_color);
ImGui::EndPopup();
}
ImGui::Checkbox("Player snaplines", &settings::player_snaplines);
ImGui::SameLine();
bool open_pslcolor_popup = ImGui::ColorButton("playersncolor", ImVec4(settings::player_snaplines_color[0], settings::player_snaplines_color[1], settings::player_snaplines_color[2], settings::player_snaplines_color[3]));
if (open_pslcolor_popup)
{
ImGui::OpenPopup("playersnpop");
}
if (ImGui::BeginPopup("playersnpop")) {
ImGui::ColorPicker4("Player snaplines color", (float*)&settings::flashlight_color);
ImGui::EndPopup();
}
ImGui::Checkbox("Azazel ESP", &settings::azazel_esp);
ImGui::SameLine();
bool open_azacolor_popup = ImGui::ColorButton("azaespcolor", ImVec4(settings::azazel_esp_color[0], settings::azazel_esp_color[1], settings::azazel_esp_color[2], settings::azazel_esp_color[3]));
if (open_azacolor_popup)
{
ImGui::OpenPopup("azaesppop");
}
if (ImGui::BeginPopup("azaesppop")) {
ImGui::ColorPicker4("Azazel ESP color", (float*)&settings::azazel_esp_color);
ImGui::EndPopup();
}
ImGui::Checkbox("Azazel snaplines", &settings::azazel_snaplines);
ImGui::SameLine();
bool open_azascolor_popup = ImGui::ColorButton("azasncolor", ImVec4(settings::azazel_snaplines_color[0], settings::azazel_snaplines_color[1], settings::azazel_snaplines_color[2], settings::azazel_snaplines_color[3]));
if (open_azascolor_popup)
{
ImGui::OpenPopup("azasnpop");
}
if (ImGui::BeginPopup("azasnpop")) {
ImGui::ColorPicker4("Azazel snaplines color", (float*)&settings::azazel_snaplines_color);
ImGui::EndPopup();
}
ImGui::Checkbox("Item ESP", &settings::item_esp);
ImGui::SameLine();
bool open_icolor_popup = ImGui::ColorButton("iespcolor", ImVec4(settings::item_esp_color[0], settings::item_esp_color[1], settings::item_esp_color[2], settings::item_esp_color[3]));
if (open_icolor_popup)
{
ImGui::OpenPopup("iesppop");
}
if (ImGui::BeginPopup("iesppop")) {
ImGui::ColorPicker4("Item ESP color", (float*)&settings::item_esp_color);
ImGui::EndPopup();
}
ImGui::Checkbox("Demon ESP", &settings::item_esp);
ImGui::SameLine();
bool open_dcolor_popup = ImGui::ColorButton("despcolor", ImVec4(settings::demon_esp_color[0], settings::demon_esp_color[1], settings::demon_esp_color[2], settings::demon_esp_color[3]));
if (open_dcolor_popup)
{
ImGui::OpenPopup("desppop");
}
if (ImGui::BeginPopup("desppop")) {
ImGui::ColorPicker4("Demon ESP color", (float*)&settings::demon_esp_color);
ImGui::EndPopup();
}
ImGui::Checkbox("Goat/Rat ESP", &settings::goat_esp);
ImGui::SameLine();
bool open_gcolor_popup = ImGui::ColorButton("gespcolor", ImVec4(settings::goat_esp_color[0], settings::goat_esp_color[1], settings::goat_esp_color[2], settings::goat_esp_color[3]));
if (open_gcolor_popup)
{
ImGui::OpenPopup("gesppop");
}
if (ImGui::BeginPopup("gesppop")) {
ImGui::ColorPicker4("Goat ESP color", (float*)&settings::goat_esp_color);
ImGui::EndPopup();
}
}
void DrawEntitiesTab() {
if (ImGui::Button("TP items to you")) {
//call tp items
}
ImGui::Spacing();
ImGui::Text("Azazel & Demons");
const char* azazel_demons_items[] = { "Sam", "Molly", "Anna", "Zara", "Ghost", "Inmate", "Demon"};
static int entity_current = 0;
ImGui::Combo("##a", &entity_current, azazel_demons_items, IM_ARRAYSIZE(azazel_demons_items));
if (ImGui::Button("Spawn")) {
//call spawn function
}
ImGui::Spacing();
ImGui::Text("Items");
const char* items_items[] = { "Hay", "First aid", "Battery", "Gasoline", "Fuse", "Food", "Egg", "Bleach", "Ritual Book", "Matchbox"};
static int item_current = 0;
ImGui::Combo("##i", &item_current, items_items, IM_ARRAYSIZE(items_items));
if (ImGui::Button("Spawn")) {
//call spawn function
}
ImGui::Spacing();
ImGui::Text("Animals");
const char* animals_items[] = { "Rat", "Goat", "Spider"};
static int animal_current = 0;
ImGui::Combo("##an", &animal_current, animals_items, IM_ARRAYSIZE(animals_items));
if (ImGui::Button("Spawn")) {
//call spawn function
}
}
void DrawMapSpecificTab() {
if (ImGui::Button("Instant win")) {
//call instant win
}
}
void DrawMiscTab() {
ImGui::Checkbox("Chat spam", &settings::chat_spam);
ImGui::InputText("Message", &settings::message);
if (ImGui::Button("Unlock Achievements")) {
//Unlock Achievements
}
if (ImGui::Button("Unlock Doors")) {
//Unlock Achievements
}
ImGui::Checkbox("Unlock all", &settings::unlock_all);
ImGui::Checkbox("Spoof level", &settings::spoof_level);
ImGui::InputInt("New level", &settings::new_level);
//normalize level
if (settings::new_level > 666) {
settings::new_level = 666;
}
else if (settings::new_level < 0) {
settings::new_level = 0;
}
ImGui::Checkbox("Change Steam name", &settings::steam_name_spoof);
ImGui::InputText("New name", &settings::new_name);
ImGui::Checkbox("Change server name", &settings::server_name_spoof);
ImGui::InputText("New name", &settings::server_name);
ImGui::Checkbox("Fly", &settings::fly);
if (ImGui::Button("Make random noise")) {
//call make random noise
}
ImGui::Checkbox("EXP modifier", &settings::exp_modifier);
ImGui::SliderInt("Amount", &settings::new_exp, 0, 5000);
ImGui::Checkbox("Walk in lobby", &settings::walk_in_lobby);
ImGui::Checkbox("Change player speed", &settings::change_player_speed);
ImGui::SliderInt("Multiplier", &settings::new_speed, 0, 10);
#if _DEBUG
ImGui::Spacing();
std::string component = "PlayerCharacterBehaviour";
ImGui::InputText("##PlayerCharacterBehaviour", &component);
if (ImGui::Button("Dump component")) {
Dump(component);
}
#endif
ImGui::Spacing();
if (ImGui::Button("Unhook")) {
CreateThread(0, 0, EjectThread, 0, 0, 0); //Unhooking
}
}
tabs current_tab = tabs::VISUALS;
void DrawMenu(bool open_menu) {
ImGui::SetNextWindowSize(ImVec2(240.000f, 300.000f), ImGuiCond_Once);
ImGui::Begin("Devour Client", NULL, 2);
ImGui::SameLine();
if (ImGui::Button("Visuals")) {//, ImVec2(0.000f, 0.000f))) {
current_tab = tabs::VISUALS;
}
ImGui::SameLine();
if (ImGui::Button("Entities", ImVec2(0.000f, 0.000f))) {
current_tab = tabs::ENTITIES;
}
ImGui::SameLine();
if (ImGui::Button("Map specific", ImVec2(0.000f, 0.000f))) {
current_tab = tabs::MAP_SPECIFIC;
}
ImGui::SameLine();
if (ImGui::Button("Misc", ImVec2(0.000f, 0.000f))) {
current_tab = tabs::MISC;
}
ImGui::Separator();
switch (current_tab) {
case tabs::VISUALS:
DrawVisualsTab();
break;
case tabs::ENTITIES:
DrawEntitiesTab();
break;
case tabs::MAP_SPECIFIC:
DrawMapSpecificTab();
break;
case tabs::MISC:
DrawMiscTab();
break;
default:
break;
}
ImGui::End();
}

View File

@@ -0,0 +1,18 @@
#pragma once
#include <Windows.h>
#pragma warning(push, 0)
#include "imgui/imgui.h"
#include "imgui/imgui_impl_win32.h"
#include "imgui/imgui_impl_dx11.h"
#include "imgui/imgui_stdlib.h"
#pragma warning(pop)
enum class tabs {
VISUALS,
ENTITIES,
MAP_SPECIFIC,
MISC
};
void InitStyle();
void DrawMenu(bool open_menu);

View File

View File

@@ -0,0 +1,3 @@
#pragma once
//misc hacks go here

View File

@@ -0,0 +1,212 @@
#include "Hooks.hpp"
#include "../Utils/Output/Output.hpp"
#include "../Features/Menu.hpp"
#include "../dllmain.hpp"
#pragma warning(push, 0) //important cuz dx11 throws so much warnings
#include <d3d11.h>
#pragma warning(pop)
#pragma comment (lib, "d3d11.lib" )
/*
//Code about hooking stuff
//Exemple of hooked function :
typedef int (__stdcall* TEST)(); //We define the function, must be the EXACT same definition as the original one
TEST test_org = NULL;
int __stdcall test_hook() //MUST BE the original calling convention
{
std::cout << "called" << std::endl;
return test_org(); //if we want to call the original one, we can just return 1 otherwise
}
//Exemple :
MH_STATUS status_test = MH_CreateHook((LPVOID*)test_sig, &test_hook, reinterpret_cast<LPVOID*>(&test_org));
//We say that for every call to the test_sig address we want to redirect it to the address of the function named test_hook (& gives the pointer to it)
//We can store the original pointer to the original function into test_org if we want to call the org later --> trampoline hook
//original_sum can be NULL if we don't want to trampoline hook
if (status_test != MH_OK) { //If it failed
print(MH_StatusToString(status)); //If we are in debug mode, we print the fail status into the console
return 0; //We exit
}
*/
typedef HRESULT(__stdcall* D3D11PresentHook) (IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags);
D3D11PresentHook phookD3D11Present = NULL;
ID3D11Device* pDevice = NULL;
ID3D11DeviceContext* pContext = NULL;
extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
HWND window = NULL;
WNDPROC oWndProc;
bool open_menu = false;
LRESULT __stdcall WndProc(const HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
if (open_menu && ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam)) {
return true;
}
ImGuiIO& io = ImGui::GetIO();
if (io.WantCaptureMouse && open_menu) {
return true;
}
return CallWindowProc(oWndProc, hWnd, uMsg, wParam, lParam);
}
static bool pressed = false;
bool initonce = false;
ID3D11RenderTargetView* mainRenderTargetViewD3D11 = NULL;
HRESULT __stdcall hookD3D11Present(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags) {
if (!initonce)
{
if (SUCCEEDED(pSwapChain->GetDevice(__uuidof(ID3D11Device), (void**)&pDevice)))
{
pDevice->GetImmediateContext(&pContext);
DXGI_SWAP_CHAIN_DESC sd;
pSwapChain->GetDesc(&sd);
window = sd.OutputWindow;
ID3D11Texture2D* pBackBuffer;
pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
pDevice->CreateRenderTargetView(pBackBuffer, NULL, &mainRenderTargetViewD3D11);
pBackBuffer->Release();
oWndProc = (WNDPROC)SetWindowLongPtr(window, GWLP_WNDPROC, (LONG_PTR)WndProc);
ImGui::CreateContext();
InitStyle();
ImGui_ImplWin32_Init(window);
ImGui_ImplDX11_Init(pDevice, pContext);
initonce = true;
}
else
return phookD3D11Present(pSwapChain, SyncInterval, Flags);
}
if (GetKeyState(VK_INSERT) & 0x8000)
pressed = true;
else if (!(GetKeyState(VK_INSERT) & 0x8000) && pressed) {
open_menu = !open_menu;
pressed = false;
}
ImGui_ImplDX11_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
if (open_menu) {
DrawMenu(open_menu);
}
ImGui::GetIO().MouseDrawCursor = open_menu;
ImGui::EndFrame();
ImGui::Render();
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
return phookD3D11Present(pSwapChain, SyncInterval, Flags);
}
DWORD_PTR* pSwapChainVtable = NULL;
DWORD_PTR* pContextVTable = NULL;
DWORD_PTR* pDeviceVTable = NULL;
IDXGISwapChain* pSwapChain;
bool HookDX11() {
HMODULE hDXGIDLL = 0;
do
{
hDXGIDLL = GetModuleHandle("dxgi.dll");
Sleep(200);
} while (!hDXGIDLL);
Sleep(100);
oWndProc = (WNDPROC)SetWindowLongPtr(window, GWLP_WNDPROC, (LONG_PTR)WndProc);
D3D_FEATURE_LEVEL requestedLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1 };
D3D_FEATURE_LEVEL obtainedLevel;
ID3D11Device* d3dDevice = nullptr;
ID3D11DeviceContext* d3dContext = nullptr;
DXGI_SWAP_CHAIN_DESC scd;
ZeroMemory(&scd, sizeof(scd));
scd.BufferCount = 1;
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
scd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
scd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
scd.OutputWindow = GetForegroundWindow();
scd.SampleDesc.Count = 1;
scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
scd.Windowed = true;
// LibOVR 0.4.3 requires that the width and height for the backbuffer is set even if
// you use windowed mode, despite being optional according to the D3D11 documentation.
scd.BufferDesc.Width = 1;
scd.BufferDesc.Height = 1;
scd.BufferDesc.RefreshRate.Numerator = 0;
scd.BufferDesc.RefreshRate.Denominator = 1;
UINT createFlags = 0;
#ifdef _DEBUG
// This flag gives you some quite wonderful debug text. Not wonderful for performance, though!
createFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
IDXGISwapChain* d3dSwapChain = 0;
if (FAILED(D3D11CreateDeviceAndSwapChain(
nullptr,
D3D_DRIVER_TYPE_HARDWARE,
nullptr,
createFlags,
requestedLevels,
sizeof(requestedLevels) / sizeof(D3D_FEATURE_LEVEL),
D3D11_SDK_VERSION,
&scd,
&pSwapChain,
&pDevice,
&obtainedLevel,
&pContext)))
{
return false;
}
pSwapChainVtable = (DWORD_PTR*)pSwapChain;
pSwapChainVtable = (DWORD_PTR*)pSwapChainVtable[0];
pContextVTable = (DWORD_PTR*)pContext;
pContextVTable = (DWORD_PTR*)pContextVTable[0];
pDeviceVTable = (DWORD_PTR*)pDevice;
pDeviceVTable = (DWORD_PTR*)pDeviceVTable[0];
if (MH_CreateHook((DWORD_PTR*)pSwapChainVtable[8], hookD3D11Present, reinterpret_cast<void**>(&phookD3D11Present)) != MH_OK) { return false; }
if (MH_EnableHook((DWORD_PTR*)pSwapChainVtable[8]) != MH_OK) { return false; }
DWORD dwOld;
VirtualProtect(phookD3D11Present, 2, PAGE_EXECUTE_READWRITE, &dwOld);
return true;
}
bool InitializeHooks() {
return MH_Initialize() == MH_OK;
}
void DisableHooks() {
MH_DisableHook(MH_ALL_HOOKS);
MH_Uninitialize();
ImGui_ImplDX11_Shutdown();
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();
if (mainRenderTargetViewD3D11) { mainRenderTargetViewD3D11->Release(); mainRenderTargetViewD3D11 = NULL; }
if (pContext) { pContext->Release(); pContext = NULL; }
if (pDevice) { pDevice->Release(); pDevice = NULL; }
pSwapChain->Release();
SetWindowLongPtr(window, GWLP_WNDPROC, (LONG_PTR)(oWndProc));
}

View File

@@ -0,0 +1,14 @@
#pragma once
#include <Windows.h>
#include <MinHook.h>
#pragma warning(push, 0)
#include "imgui/imgui.h"
#include "imgui/imgui_impl_win32.h"
#include "imgui/imgui_impl_dx11.h"
#pragma warning(pop)
bool HookDX11();
bool InitializeHooks();
void DisableHooks();

View File

@@ -0,0 +1,35 @@
#include "Dumper.hpp"
#include "../Output/Output.hpp"
void Dump(std::string component) {
print("\n\n\n");
print("Dumping %s\n\n", component.c_str());
auto list = Unity::Object::FindObjectsOfType<Unity::CComponent>(component.c_str());
for (int i = 0; i < list->m_uMaxLength + 1; i++)
{
if (!list->operator[](i))
continue;
Unity::CGameObject* object = list->operator[](i)->GetMemberValue<Unity::CGameObject*>("gameObject");
print("%s\n", object->GetName()->ToString().c_str()); //SurvivalPlayer(Clone)
auto components = object->GetComponents(UNITY_COMPONENT_CLASS);
for (int n = 0; n < components->m_uMaxLength; n++)
{
if (!components->operator[](n))
continue;
print("| -> %s::%s\n", components->operator[](n)->m_Object.m_pClass->m_pNamespace, components->operator[](n)->m_Object.m_pClass->m_pName);
}
Unity::CComponent* BoltEntity = object->GetComponent("BoltEntity");
if (BoltEntity)
{
print("|-------- owner:%d \n", BoltEntity->CallMethod<bool>("get_IsOwner")); //local player check?
if (BoltEntity->CallMethod<bool>("get_IsOwner"))
{
}
}
}
}

View File

@@ -0,0 +1,4 @@
#pragma once
#include "../Dependencies/IL2CPP_Resolver/il2cpp_resolver.hpp"
void Dump(std::string component);

Some files were not shown because too many files have changed in this diff Show More