geode/loader/include/Geode/platform/windows.hpp

141 lines
4.1 KiB
C++
Raw Normal View History

2022-07-30 12:24:03 -04:00
#pragma once
2022-10-30 14:59:20 -04:00
#pragma warning(default : 4067)
#pragma warning(disable : 4251) // dll-interface
#pragma warning(disable : 4244) // narrowing conversion
2022-07-30 12:24:03 -04:00
2022-10-30 14:59:20 -04:00
#include <Windows.h>
#include <cstring>
2022-07-30 12:24:03 -04:00
#include <type_traits>
#include <typeinfo>
2024-08-19 12:19:29 -04:00
#include <memory>
2022-07-30 12:24:03 -04:00
namespace geode {
struct PlatformInfo {
HMODULE m_hmod;
};
}
namespace geode::base {
2022-10-30 14:59:20 -04:00
GEODE_NOINLINE inline uintptr_t get() {
static uintptr_t base = reinterpret_cast<uintptr_t>(GetModuleHandle(0));
return base;
}
GEODE_NOINLINE inline uintptr_t getCocos() {
static uintptr_t base = reinterpret_cast<uintptr_t>(GetModuleHandleA("libcocos2d.dll"));
return base;
}
2022-07-30 12:24:03 -04:00
}
2024-06-01 13:23:03 -04:00
2022-07-30 12:24:03 -04:00
namespace geode::cast {
2024-06-01 13:23:03 -04:00
template <class Type>
struct ShrunkPointer {
uint32_t m_ptrOffset;
Type* into(uintptr_t base) {
return reinterpret_cast<Type*>(base + m_ptrOffset);
}
};
2022-10-30 14:59:20 -04:00
struct TypeDescriptorType {
void* m_typeinfoTable;
2024-06-01 13:23:03 -04:00
intptr_t m_spare;
2022-10-30 14:59:20 -04:00
char m_typeDescriptorName[0x100];
};
struct ClassDescriptorType;
struct BaseClassDescriptorType {
2024-06-01 13:23:03 -04:00
ShrunkPointer<TypeDescriptorType> m_typeDescriptor;
2022-10-30 14:59:20 -04:00
int32_t m_numContainedBases;
int32_t m_memberDisplacement[3];
int32_t m_attributes;
2024-06-01 13:23:03 -04:00
ShrunkPointer<ClassDescriptorType> m_classDescriptor;
};
struct BaseClassArrayType {
ShrunkPointer<BaseClassDescriptorType> m_descriptorEntries[0x100];
2022-10-30 14:59:20 -04:00
};
struct ClassDescriptorType {
int32_t m_signature;
int32_t m_attributes;
int32_t m_numBaseClasses;
2024-06-01 13:23:03 -04:00
ShrunkPointer<BaseClassArrayType> m_baseClassArray;
2022-10-30 14:59:20 -04:00
};
struct CompleteLocatorType {
int32_t m_signature;
int32_t m_offset;
int32_t m_cdOffset;
2024-06-01 13:23:03 -04:00
ShrunkPointer<TypeDescriptorType> m_typeDescriptor;
ShrunkPointer<ClassDescriptorType> m_classDescriptor;
#ifdef GEODE_IS_X64
int32_t m_locatorOffset;
#endif
2022-10-30 14:59:20 -04:00
};
struct MetaPointerType {
CompleteLocatorType* m_completeLocator;
};
struct VftableType {
void* m_vftable[0x100];
};
struct CompleteVftableType : MetaPointerType, VftableType {};
template <class After, class Before>
inline After typeinfo_cast(Before ptr) {
static_assert(
std::is_polymorphic_v<std::remove_pointer_t<Before>>, "Input is not a polymorphic type"
);
2023-02-11 12:31:30 -05:00
if (!ptr) {
return After();
}
2022-10-30 14:59:20 -04:00
auto basePtr = dynamic_cast<void*>(ptr);
auto vftable = *reinterpret_cast<VftableType**>(basePtr);
auto metaPtr = static_cast<MetaPointerType*>(static_cast<CompleteVftableType*>(vftable));
auto afterDesc =
reinterpret_cast<TypeDescriptorType const*>(&typeid(std::remove_pointer_t<After>));
auto afterIdent = static_cast<char const*>(afterDesc->m_typeDescriptorName);
2024-06-01 13:23:03 -04:00
#ifdef GEODE_IS_X64
auto locatorOffset = metaPtr->m_completeLocator->m_locatorOffset;
auto base = reinterpret_cast<uintptr_t>(metaPtr->m_completeLocator) - locatorOffset;
#else
auto base = 0;
#endif
auto classDesc = metaPtr->m_completeLocator->m_classDescriptor.into(base);
2022-10-30 14:59:20 -04:00
for (int32_t i = 0; i < classDesc->m_numBaseClasses; ++i) {
2024-06-01 13:23:03 -04:00
auto entry = classDesc->m_baseClassArray.into(base)->m_descriptorEntries[i].into(base);
2022-10-30 14:59:20 -04:00
auto optionIdent = static_cast<char const*>(
2024-06-01 13:23:03 -04:00
entry->m_typeDescriptor.into(base)->m_typeDescriptorName
2022-10-30 14:59:20 -04:00
);
2024-06-01 13:23:03 -04:00
auto optionOffset = entry->m_memberDisplacement[0];
2022-10-30 14:59:20 -04:00
if (std::strcmp(afterIdent, optionIdent) == 0) {
auto afterPtr = reinterpret_cast<std::byte*>(basePtr) + optionOffset;
return reinterpret_cast<After>(afterPtr);
}
}
return nullptr;
}
2024-08-19 12:19:29 -04:00
template<class T, class U>
std::shared_ptr<T> typeinfo_pointer_cast(std::shared_ptr<U> const& r) noexcept {
// https://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast
auto p = typeinfo_cast<typename std::shared_ptr<T>::element_type*>(r.get());
return std::shared_ptr<T>(r, p);
}
2022-07-30 12:24:03 -04:00
}