mirror of
https://github.com/quizhizhe/LiteLoaderBDS-1.16.40.git
synced 2025-06-06 20:03:51 +00:00
552 lines
24 KiB
C++
552 lines
24 KiB
C++
#include "NativeAPI.h"
|
|
|
|
#include <HookAPI.h>
|
|
#include <magic_enum/magic_enum.hpp>
|
|
#include "../Tools/Demangler/include/MicrosoftDemangle.h"
|
|
|
|
|
|
Concurrency::concurrent_unordered_map<std::string, NativeFunction> NativeFunction::parsedSymbol;
|
|
|
|
#define NATIVE_CHECK_ARG_TYPE(TYPE) \
|
|
if (args[i].getKind() != TYPE) { \
|
|
logger.error("Wrong type of argument!"); \
|
|
logger.error("In Symbol: " + funcSymbol->mSymbol); \
|
|
logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); \
|
|
return Local<Value>(); \
|
|
}
|
|
|
|
#define NATIVE_CHECK_ARG_CLASS(TYPE) \
|
|
if (!IsInstanceOf<TYPE>(args[i])) { \
|
|
logger.error("Wrong type of argument!"); \
|
|
logger.error("In Symbol: " + funcSymbol->mSymbol); \
|
|
logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName); \
|
|
return Local<Value>(); \
|
|
}
|
|
|
|
Local<Value> NativeFunction::callNativeFunction(DCCallVM* vm, NativeFunction* funcSymbol, const Arguments& args) {
|
|
if (args.size() < funcSymbol->mParams.size()) {
|
|
logger.error("Too Few arguments!");
|
|
logger.error("In Component: NativeCall");
|
|
logger.error("In Symbol: " + funcSymbol->mSymbol);
|
|
logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName);
|
|
return Local<Value>();
|
|
}
|
|
|
|
dcReset(vm);
|
|
for (int i = 0; i < funcSymbol->mParams.size(); ++i) {
|
|
switch (funcSymbol->mParams[i]) {
|
|
case NativeFunction::Types::Bool:
|
|
NATIVE_CHECK_ARG_TYPE(ValueKind::kBoolean);
|
|
dcArgChar(vm, args[i].asBoolean().value());
|
|
break;
|
|
case NativeFunction::Types::Char:
|
|
case NativeFunction::Types::UnsignedChar:
|
|
NATIVE_CHECK_ARG_TYPE(ValueKind::kNumber);
|
|
dcArgChar(vm, (char)args[i].asNumber().toInt32());
|
|
break;
|
|
case NativeFunction::Types::Short:
|
|
case NativeFunction::Types::UnsignedShort:
|
|
NATIVE_CHECK_ARG_TYPE(ValueKind::kNumber);
|
|
dcArgShort(vm, (short)args[i].asNumber().toInt32());
|
|
break;
|
|
case NativeFunction::Types::Int:
|
|
case NativeFunction::Types::UnsignedInt:
|
|
NATIVE_CHECK_ARG_TYPE(ValueKind::kNumber);
|
|
dcArgInt(vm, (int)args[i].asNumber().toInt32());
|
|
break;
|
|
case NativeFunction::Types::Long:
|
|
case NativeFunction::Types::UnsignedLong:
|
|
NATIVE_CHECK_ARG_TYPE(ValueKind::kNumber);
|
|
dcArgLong(vm, (long)args[i].asNumber().toInt32());
|
|
break;
|
|
case NativeFunction::Types::LongLong:
|
|
case NativeFunction::Types::UnsignedLongLong:
|
|
NATIVE_CHECK_ARG_TYPE(ValueKind::kNumber);
|
|
dcArgLongLong(vm, args[i].asNumber().toInt64());
|
|
break;
|
|
case NativeFunction::Types::Float:
|
|
NATIVE_CHECK_ARG_TYPE(ValueKind::kNumber);
|
|
dcArgFloat(vm, args[i].asNumber().toFloat());
|
|
break;
|
|
case NativeFunction::Types::Double:
|
|
NATIVE_CHECK_ARG_TYPE(ValueKind::kNumber);
|
|
dcArgDouble(vm, args[i].asNumber().toDouble());
|
|
break;
|
|
case NativeFunction::Types::Pointer:
|
|
switch (args[i].getKind()) {
|
|
case ValueKind::kObject:
|
|
NATIVE_CHECK_ARG_CLASS(NativePointer);
|
|
dcArgPointer(vm, NativePointer::extract(args[i]));
|
|
break;
|
|
case ValueKind::kNumber:
|
|
NATIVE_CHECK_ARG_TYPE(ValueKind::kNumber);
|
|
dcArgPointer(vm, (void*)args[i].asNumber().toInt64());
|
|
break;
|
|
case ValueKind::kNull:
|
|
default:
|
|
dcArgPointer(vm, nullptr);
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
Local<Value> res;
|
|
DCpointer func = (DCpointer)funcSymbol->mFunction;
|
|
switch (funcSymbol->mReturnVal) {
|
|
case NativeFunction::Types::Void:
|
|
dcCallVoid(vm, func);
|
|
break;
|
|
case NativeFunction::Types::Bool: {
|
|
// in c, bool is the alias of int
|
|
// [c]#define bool int, sizeof(bool) == 4
|
|
// but in cpp, bool represent a true/false value
|
|
// it'a a builtin type, sizeof(bool) == sizeof(char) == 1
|
|
res = Boolean::newBoolean(dcCallChar(vm, func));
|
|
break;
|
|
}
|
|
case NativeFunction::Types::Char:
|
|
case NativeFunction::Types::UnsignedChar:
|
|
res = Number::newNumber(dcCallChar(vm, func));
|
|
break;
|
|
case NativeFunction::Types::Short:
|
|
case NativeFunction::Types::UnsignedShort:
|
|
res = Number::newNumber(dcCallShort(vm, func));
|
|
break;
|
|
case NativeFunction::Types::Int:
|
|
case NativeFunction::Types::UnsignedInt:
|
|
res = Number::newNumber(dcCallInt(vm, func));
|
|
break;
|
|
case NativeFunction::Types::Long:
|
|
case NativeFunction::Types::UnsignedLong:
|
|
res = Number::newNumber((int)dcCallLong(vm, func));
|
|
break;
|
|
case NativeFunction::Types::LongLong:
|
|
case NativeFunction::Types::UnsignedLongLong:
|
|
res = Number::newNumber(dcCallLongLong(vm, func));
|
|
break;
|
|
case NativeFunction::Types::Float:
|
|
res = Number::newNumber(dcCallFloat(vm, func));
|
|
break;
|
|
case NativeFunction::Types::Double:
|
|
res = Number::newNumber(dcCallDouble(vm, func));
|
|
break;
|
|
case NativeFunction::Types::Pointer:
|
|
res = NativePointer::newNativePointer((NativePointer*)dcCallPointer(vm, func));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return res;
|
|
}
|
|
char NativeFunction::getTypeSignature(NativeFunction::Types type) {
|
|
switch (type) {
|
|
case NativeFunction::Types::Bool:
|
|
return 'B';
|
|
break;
|
|
case NativeFunction::Types::Char:
|
|
return 'c';
|
|
break;
|
|
case NativeFunction::Types::UnsignedChar:
|
|
return 'C';
|
|
break;
|
|
case NativeFunction::Types::Short:
|
|
return 's';
|
|
break;
|
|
case NativeFunction::Types::UnsignedShort:
|
|
return 'S';
|
|
break;
|
|
case NativeFunction::Types::Int:
|
|
return 'i';
|
|
break;
|
|
case NativeFunction::Types::UnsignedInt:
|
|
return 'I';
|
|
break;
|
|
case NativeFunction::Types::Long:
|
|
return 'j';
|
|
break;
|
|
case NativeFunction::Types::UnsignedLong:
|
|
return 'J';
|
|
break;
|
|
case NativeFunction::Types::LongLong:
|
|
return 'l';
|
|
break;
|
|
case NativeFunction::Types::UnsignedLongLong:
|
|
return 'L';
|
|
break;
|
|
case NativeFunction::Types::Float:
|
|
return 'f';
|
|
break;
|
|
case NativeFunction::Types::Double:
|
|
return 'd';
|
|
break;
|
|
case NativeFunction::Types::Pointer:
|
|
return 'p';
|
|
break;
|
|
default:
|
|
return 'v';
|
|
break;
|
|
}
|
|
}
|
|
inline std::string NativeFunction::buildDynCallbackSig() {
|
|
std::string result;
|
|
size_t params_size = mParams.size();
|
|
result.reserve(params_size + 2);
|
|
for (int i = 0; i < params_size; ++i) {
|
|
result[i] = getTypeSignature(mParams[i]);
|
|
}
|
|
result[params_size + 0] = ')';
|
|
result[params_size + 1] = getTypeSignature(mReturnVal);
|
|
return result;
|
|
}
|
|
NativeFunction::Types NativeFunction::getNativeType(llvm::ms_demangle::Node* type) {
|
|
using namespace llvm::ms_demangle;
|
|
if (type) {
|
|
if (type->kind() == NodeKind::PrimitiveType) {
|
|
switch (((PrimitiveTypeNode*)type)->PrimKind) {
|
|
case PrimitiveKind::Bool:
|
|
return NativeFunction::Types::Bool;
|
|
break;
|
|
case PrimitiveKind::Char:
|
|
return NativeFunction::Types::Char;
|
|
break;
|
|
case PrimitiveKind::Uchar:
|
|
return NativeFunction::Types::UnsignedChar;
|
|
break;
|
|
case PrimitiveKind::Short:
|
|
return NativeFunction::Types::Short;
|
|
break;
|
|
case PrimitiveKind::Ushort:
|
|
return NativeFunction::Types::UnsignedShort;
|
|
break;
|
|
case PrimitiveKind::Int:
|
|
return NativeFunction::Types::Int;
|
|
break;
|
|
case PrimitiveKind::Uint:
|
|
return NativeFunction::Types::UnsignedInt;
|
|
break;
|
|
case PrimitiveKind::Long:
|
|
return NativeFunction::Types::Long;
|
|
break;
|
|
case PrimitiveKind::Ulong:
|
|
return NativeFunction::Types::UnsignedLong;
|
|
break;
|
|
case PrimitiveKind::Int64:
|
|
return NativeFunction::Types::LongLong;
|
|
break;
|
|
case PrimitiveKind::Uint64:
|
|
return NativeFunction::Types::UnsignedLongLong;
|
|
break;
|
|
case PrimitiveKind::Float:
|
|
return NativeFunction::Types::Float;
|
|
break;
|
|
case PrimitiveKind::Double:
|
|
return NativeFunction::Types::Double;
|
|
break;
|
|
default:
|
|
return NativeFunction::Types::Void;
|
|
}
|
|
} else if (type->kind() == NodeKind::PointerType || type->kind() == NodeKind::NamedIdentifier) {
|
|
return NativeFunction::Types::Pointer;
|
|
} else if (type->kind() == NodeKind::TagType) {
|
|
switch (((TagTypeNode*)type)->Tag) {
|
|
case TagKind::Enum:
|
|
return NativeFunction::Types::Int;
|
|
default:
|
|
return NativeFunction::Types::Pointer;
|
|
}
|
|
}
|
|
}
|
|
return NativeFunction::Types::Void;
|
|
}
|
|
|
|
NativeFunction NativeFunction::getOrParse(const std::string& symbol) {
|
|
// query cache
|
|
if (auto iter = parsedSymbol.find(symbol); iter != parsedSymbol.end()) {
|
|
return iter->second; // return by copy
|
|
}
|
|
// no cache found
|
|
using namespace llvm::ms_demangle;
|
|
NativeFunction result;
|
|
|
|
result.mFunction = dlsym_real(symbol.c_str());
|
|
result.mSymbol = symbol;
|
|
|
|
Demangler demangler;
|
|
StringView symbolView{symbol.c_str()};
|
|
SymbolNode* AST = demangler.parse(symbolView);
|
|
if (demangler.Error)
|
|
throw std::runtime_error("failed to demangle symbol");
|
|
if (AST->kind() != NodeKind::FunctionSymbol)
|
|
throw std::runtime_error("mangled name is not a function");
|
|
auto funcAST = static_cast<FunctionSymbolNode*>(AST);
|
|
result.mReturnVal = getNativeType(funcAST->Signature->ReturnType);
|
|
if (funcAST->Signature->Quals & Q_Pointer64)
|
|
result.mParams.push_back(NativeFunction::Types::Pointer);
|
|
|
|
if (funcAST->Signature->Params) {
|
|
result.mParams.reserve(funcAST->Signature->Params->Count + 1);
|
|
for (auto i = 0; i < funcAST->Signature->Params->Count; ++i) {
|
|
result.mParams.push_back(getNativeType(funcAST->Signature->Params->Nodes[i]));
|
|
}
|
|
}
|
|
|
|
// push into cache
|
|
parsedSymbol.insert({symbol, result});
|
|
|
|
return result;
|
|
}
|
|
Local<Value> ScriptNativeFunction::fromSymbol(const Arguments& args) {
|
|
using namespace llvm::ms_demangle;
|
|
CHECK_ARGS_COUNT(args, 1);
|
|
CHECK_ARG_TYPE(args[0], ValueKind::kString);
|
|
const std::string symbol = args[0].toStr();
|
|
|
|
auto scriptResult = args.engine()->newNativeClass<ScriptNativeFunction>();
|
|
ScriptNativeFunction* result = args.engine()->getNativeInstance<ScriptNativeFunction>(scriptResult);
|
|
|
|
result->cloneFrom(getOrParse(symbol));
|
|
|
|
return scriptResult;
|
|
}
|
|
Local<Value> ScriptNativeFunction::fromDescription(const Arguments& args) {
|
|
auto scriptResult = args.engine()->newNativeClass<ScriptNativeFunction>();
|
|
ScriptNativeFunction* result = args.engine()->getNativeInstance<ScriptNativeFunction>(scriptResult);
|
|
CHECK_ARGS_COUNT(args, 1);
|
|
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
|
|
size_t argsSize = args.size();
|
|
result->mReturnVal = magic_enum::enum_cast<NativeFunction::Types>(args[0].toInt()).value_or(NativeFunction::Types::Void);
|
|
for (size_t i = 1; i < argsSize; i++) {
|
|
CHECK_ARG_TYPE(args[i], ValueKind::kNumber);
|
|
result->mParams.push_back(magic_enum::enum_cast<NativeFunction::Types>(args[i].toInt()).value_or(NativeFunction::Types::Void));
|
|
}
|
|
return scriptResult;
|
|
}
|
|
|
|
Local<Value> ScriptNativeFunction::fromScript(const Arguments& args) {
|
|
CHECK_ARG_TYPE(args[args.size() - 1], ValueKind::kFunction);
|
|
auto scriptResult = args.engine()->newNativeClass<DynamicHookData>(args.thiz());
|
|
DynamicHookData* nativeScriptFunction = args.engine()->getNativeInstance<DynamicHookData>(scriptResult);
|
|
|
|
CHECK_ARG_TYPE(args[0], ValueKind::kNumber);
|
|
size_t argsSize = args.size();
|
|
nativeScriptFunction->mReturnVal = magic_enum::enum_cast<NativeFunction::Types>(args[0].toInt()).value_or(NativeFunction::Types::Void);
|
|
for (size_t i = 1; i < argsSize - 1; i++) {
|
|
CHECK_ARG_TYPE(args[i], ValueKind::kNumber);
|
|
nativeScriptFunction->mParams.push_back(magic_enum::enum_cast<NativeFunction::Types>(args[i].toInt()).value_or(NativeFunction::Types::Void));
|
|
}
|
|
|
|
nativeScriptFunction->mEngine = args.engine();
|
|
nativeScriptFunction->mNativeCallack = dcbNewCallback(nativeScriptFunction->buildDynCallbackSig().c_str(), &nativeCallbackHandler, nativeScriptFunction);
|
|
nativeScriptFunction->mFunction = nativeScriptFunction->mNativeCallack;
|
|
nativeScriptFunction->mScriptCallback = args[args.size() - 1].asFunction();
|
|
|
|
return scriptResult;
|
|
}
|
|
|
|
Local<Value> NativeFunction::getCallableFunction() {
|
|
return Function::newFunction([this](const Arguments& args) -> Local<Value> {
|
|
return callNativeFunction(ENGINE_OWN_DATA()->dynamicCallVM, this, args);
|
|
});
|
|
}
|
|
char NativeFunction::nativeCallbackHandler(DCCallback* cb, DCArgs* args, DCValue* result, void* userdata) {
|
|
DynamicHookData* hookInfo = (DynamicHookData*)userdata;
|
|
|
|
EngineScope enter(hookInfo->mEngine);
|
|
try {
|
|
vector<Local<Value>> paras;
|
|
for (int i = 0; i < hookInfo->mParams.size(); ++i) {
|
|
switch (hookInfo->mParams[i]) {
|
|
case NativeFunction::Types::Bool:
|
|
paras.emplace_back(Boolean::newBoolean(dcbArgBool(args)));
|
|
break;
|
|
case NativeFunction::Types::Char:
|
|
paras.emplace_back(Number::newNumber(dcbArgChar(args)));
|
|
break;
|
|
case NativeFunction::Types::UnsignedChar:
|
|
paras.emplace_back(Number::newNumber(dcbArgUChar(args)));
|
|
break;
|
|
case NativeFunction::Types::Short:
|
|
paras.emplace_back(Number::newNumber(dcbArgShort(args)));
|
|
break;
|
|
case NativeFunction::Types::UnsignedShort:
|
|
paras.emplace_back(Number::newNumber(dcbArgUShort(args)));
|
|
break;
|
|
case NativeFunction::Types::Int:
|
|
paras.emplace_back(Number::newNumber(dcbArgInt(args)));
|
|
break;
|
|
case NativeFunction::Types::UnsignedInt:
|
|
paras.emplace_back(Number::newNumber((int)dcbArgUInt(args)));
|
|
break;
|
|
case NativeFunction::Types::Long:
|
|
paras.emplace_back(Number::newNumber((int)dcbArgLong(args)));
|
|
break;
|
|
case NativeFunction::Types::UnsignedLong:
|
|
paras.emplace_back(Number::newNumber((int)dcbArgULong(args)));
|
|
break;
|
|
case NativeFunction::Types::LongLong:
|
|
paras.emplace_back(Number::newNumber(dcbArgLongLong(args)));
|
|
break;
|
|
case NativeFunction::Types::UnsignedLongLong:
|
|
paras.emplace_back(Number::newNumber((long long)dcbArgULongLong(args)));
|
|
break;
|
|
case NativeFunction::Types::Float:
|
|
paras.emplace_back(Number::newNumber(dcbArgFloat(args)));
|
|
break;
|
|
case NativeFunction::Types::Double:
|
|
paras.emplace_back(Number::newNumber(dcbArgDouble(args)));
|
|
break;
|
|
case NativeFunction::Types::Pointer:
|
|
paras.emplace_back(NativePointer::newNativePointer((NativePointer*)dcbArgPointer(args)));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
Local<Value> res = hookInfo->mScriptCallback.get().call({}, paras);
|
|
|
|
switch (hookInfo->mReturnVal) {
|
|
case NativeFunction::Types::Bool:
|
|
result->c = res.asBoolean().value();// pass bool by char
|
|
break;
|
|
case NativeFunction::Types::Char:
|
|
result->c = (char)res.toInt();
|
|
break;
|
|
case NativeFunction::Types::UnsignedChar:
|
|
result->C = (unsigned char)res.toInt();
|
|
break;
|
|
case NativeFunction::Types::Short:
|
|
result->s = (short)res.toInt();
|
|
break;
|
|
case NativeFunction::Types::UnsignedShort:
|
|
result->S = (unsigned short)res.toInt();
|
|
break;
|
|
case NativeFunction::Types::Int:
|
|
result->i = (int)res.toInt();
|
|
break;
|
|
case NativeFunction::Types::UnsignedInt:
|
|
result->I = (unsigned int)res.toInt();
|
|
break;
|
|
case NativeFunction::Types::Long:
|
|
result->j = (long)res.toInt();
|
|
break;
|
|
case NativeFunction::Types::UnsignedLong:
|
|
result->J = (unsigned long)res.toInt();
|
|
break;
|
|
case NativeFunction::Types::LongLong:
|
|
result->l = (long long)res.asNumber().toInt64();
|
|
break;
|
|
case NativeFunction::Types::UnsignedLongLong:
|
|
result->L = (unsigned long long)res.asNumber().toInt64();
|
|
break;
|
|
case NativeFunction::Types::Float:
|
|
result->f = res.asNumber().toFloat();
|
|
break;
|
|
case NativeFunction::Types::Double:
|
|
result->d = res.asNumber().toDouble();
|
|
break;
|
|
case NativeFunction::Types::Pointer:
|
|
switch (res.getKind()) {
|
|
case ValueKind::kObject:
|
|
result->p = NativePointer::extract(res);
|
|
break;
|
|
case ValueKind::kNumber:
|
|
result->p = (void*)res.asNumber().toInt64();
|
|
break;
|
|
case ValueKind::kNull:
|
|
default:
|
|
result->p = nullptr;
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} catch (const Exception& e) {
|
|
logger.error("Hook Callback Failed!");
|
|
logger.error("Message: {}",e.message());
|
|
logger.error("StackTrace: {}", e.stacktrace());
|
|
logger.error("In Symbol: " + hookInfo->mSymbol);
|
|
logger.error("In Plugin: " + ENGINE_OWN_DATA()->pluginName);
|
|
}
|
|
|
|
return NativeFunction::getTypeSignature(hookInfo->mReturnVal);
|
|
}
|
|
|
|
|
|
Local<Value> ScriptNativeFunction::setAddress(const Local<Value>& value) {
|
|
auto engine = this->getScriptEngine();
|
|
bool isNativePointer = engine->isInstanceOf<NativePointer>(value);
|
|
bool isInt64 = value.getKind() == ValueKind::kNumber;
|
|
if (isNativePointer) {
|
|
NativePointer* ptr = engine->getNativeInstance<NativePointer>(value);
|
|
this->mFunction = ptr->unwrap();
|
|
return Local<Value>();
|
|
}
|
|
if (isInt64) {
|
|
*((__int64*)&this->mFunction) = value.asNumber().toInt64();
|
|
return Local<Value>();
|
|
}
|
|
LOG_WRONG_ARG_TYPE();
|
|
return Local<Value>();
|
|
}
|
|
Local<Value> ScriptNativeFunction::getAddress() {
|
|
try {
|
|
return Number::newNumber(*((__int64*)&this->mFunction));
|
|
}
|
|
CATCH("Fail in getUchar!")
|
|
}
|
|
|
|
Local<Value> ScriptNativeFunction::hook(const Arguments& args) {
|
|
CHECK_ARGS_COUNT(args, 1);
|
|
CHECK_ARG_TYPE(args[0], ValueKind::kFunction);
|
|
auto scriptResult = args.engine()->newNativeClass<DynamicHookData>(args.thiz());
|
|
DynamicHookData* hookSymbol = args.engine()->getNativeInstance<DynamicHookData>(scriptResult);
|
|
hookSymbol->cloneFrom(NativeFunction(*args.engine()->getNativeInstance<ScriptNativeFunction>(args.thiz())));
|
|
hookSymbol->mEngine = args.engine();
|
|
hookSymbol->mNativeCallack = dcbNewCallback(hookSymbol->buildDynCallbackSig().c_str(), &nativeCallbackHandler, hookSymbol);
|
|
hookSymbol->mScriptCallback = args[0].asFunction();
|
|
void* hookOriginl = nullptr;
|
|
int hookResult = HookFunction(hookSymbol->mFunction, &hookOriginl, hookSymbol->mNativeCallack);
|
|
hookSymbol->mFunction = hookOriginl;
|
|
return scriptResult;
|
|
}
|
|
|
|
ClassDefine<void> NativeTypeEnumBuilder =
|
|
defineClass("NativeTypes")
|
|
.property("Void", &NativeFunction::getType<NativeFunction::Types::Void>)
|
|
.property("Bool", &NativeFunction::getType<NativeFunction::Types::Bool>)
|
|
.property("Char", &NativeFunction::getType<NativeFunction::Types::Char>)
|
|
.property("UnsignedChar", &NativeFunction::getType<NativeFunction::Types::UnsignedChar>)
|
|
.property("Short", &NativeFunction::getType<NativeFunction::Types::Short>)
|
|
.property("UnsignedShort", &NativeFunction::getType<NativeFunction::Types::UnsignedShort>)
|
|
.property("Int", &NativeFunction::getType<NativeFunction::Types::Int>)
|
|
.property("UnsignedInt", &NativeFunction::getType<NativeFunction::Types::UnsignedInt>)
|
|
.property("Long", &NativeFunction::getType<NativeFunction::Types::Long>)
|
|
.property("UnsignedLong", &NativeFunction::getType<NativeFunction::Types::UnsignedLong>)
|
|
.property("LongLong", &NativeFunction::getType<NativeFunction::Types::LongLong>)
|
|
.property("UnsignedLongLong", &NativeFunction::getType<NativeFunction::Types::UnsignedLongLong>)
|
|
.property("Float", &NativeFunction::getType<NativeFunction::Types::Float>)
|
|
.property("Double", &NativeFunction::getType<NativeFunction::Types::Double>)
|
|
.property("Pointer", &NativeFunction::getType<NativeFunction::Types::Pointer>)
|
|
.build();
|
|
|
|
ClassDefine<ScriptNativeFunction> NativeCallBuilder =
|
|
defineClass<ScriptNativeFunction>("NativeFunction")
|
|
.constructor()
|
|
.function("fromSymbol", &ScriptNativeFunction::fromSymbol)
|
|
.function("fromDescription", &ScriptNativeFunction::fromDescription)
|
|
.function("fromScript", &ScriptNativeFunction::fromScript)
|
|
.instanceFunction("hook", &ScriptNativeFunction::hook)
|
|
.instanceProperty("call", &ScriptNativeFunction::getCallableFunction)
|
|
.instanceProperty("address", &ScriptNativeFunction::getAddress, &ScriptNativeFunction::setAddress)
|
|
.build();
|
|
|
|
ClassDefine<DynamicHookData> NativeHookBuilder =
|
|
defineClass<DynamicHookData>("NativeHook")
|
|
.constructor()
|
|
.instanceProperty("call", &ScriptNativeFunction::getCallableFunction)
|
|
.instanceProperty("address", &ScriptNativeFunction::getAddress, &ScriptNativeFunction::setAddress)
|
|
.build(); |