// Класс-заглушка
class UObject {};
// Структура кадра стека UnrealScript
struct FFrame {
int* ftable; // Указатель на таблицу функций
void* Node; // Указатель на узел
UObject* Object; // Указатель на объект
BYTE* Code; // Указатель на код
BYTE* Locals; // Указатель на локальные переменные
INT LineNum; // Номер строки
};
// Тип для нативных функций
typedef void(__stdcall* Native)(FFrame&, void* const);
// Тип для функции регистрации нативных функций в UnrealScript
typedef BYTE(__cdecl* GRegisterNative_fnType)(INT iNative, const Native& Func);
//Функция которая должна вернуть строку в UnrealScript
static void __stdcall GetMyString(struct FFrame& Stack, void* Result) {
const wchar_t* source = L"Hello, world!";
size_t len = wcslen(source) + 1;
// Выделяем память + проверка на ошибку
wchar_t* buffer = (wchar_t*)malloc(len * sizeof(wchar_t));
if (buffer == NULL) {
*((wchar_t**)Result) = NULL;
return;
}
// Используем wcscpy_s
errno_t err = wcscpy_s(buffer, len, source); // len - размер буфера
if (err != 0) {
free(buffer); // Обязательно освободить память в случае ошибки
*((wchar_t**)Result) = NULL;
return;
}
*((wchar_t**)Result) = buffer;
}
// Подключение Core.dll
void hookCore() {
HMODULE hCore = GetModuleHandleA("Core.dll"); // Получение дескриптора Core.dll
// Проверка на успешное получение дескриптора
if (hCore) {
GRegisterNative_fnType GRegisterNative_fn = (GRegisterNative_fnType)GetProcAddress(hCore, "?GRegisterNative@@YAEHABQ8UObject@@AEXAAUFFrame@@QAX@Z@Z");
// Проверка на успешное получение адреса функции
if (GRegisterNative_fn) {
// Регистрация нативных функций в UnrealScript
GRegisterNative_fn(1255, &GetMyString);
}
}
}
// Точка входа DLL
extern "C" __declspec(dllexport)
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
// Отключение отслеживания вызовов функций библиотеки
DisableThreadLibraryCalls(hModule);
hookCore();
}
return TRUE;
}
native(1255) final function string GetMyString();
AddSystemMessageString("DLL_TEXT="@GetMyString()); //string Вывод системных сообщений в чат
Могли бы вы привести пример, я пока не понимаю как это работает(реализовать класс FString. Он имеет не просто массив байт но и размер и важно использовать менеджер памяти клиента для создания/удаления строки.
тут уже сами изучайтеМогли бы вы привести пример, я пока не понимаю как это работает(
Разве клиент не сам отвечает за освобождение памяти?тут уже сами изучайте
у тебя даже по ошибки видно что она идет в освобождении. Чтобы он смог удалить он должен знать о ней.Разве клиент не сам отвечает за освобождение памяти?
Хорошо, спасибо, я понял. Буду разбираться. Буду очень признателен, если кто-то сможет дать мне более подробные разъяснения.у тебя даже по ошибки видно что она идет в освобождении. Чтобы он смог удалить он должен знать о ней.
Fyyre и акуму заливали сдк для грации и интерлюда, там это есть. Точно уже не вспомню чью работу я взял себе (мне нужен был только FString)Могли бы вы привести пример, я пока не понимаю как это работает(
template<class T>
struct TArray
{
friend struct FString;
public:
inline TArray()
{
Data = nullptr;
Count = Max = 0;
};
inline size_t Num() const
{
return Count;
};
inline T& operator[](size_t i)
{
return Data[i];
};
inline const T& operator[](size_t i) const
{
return Data[i];
};
inline bool IsValidIndex(size_t i) const
{
return i < Num();
}
inline T& GetByIndex(size_t i)
{
return Data[i];
}
inline const T& GetByIndex(size_t i) const
{
return Data[i];
}
private:
T* Data;
int32_t Count;
int32_t Max;
};
struct FString : private TArray<wchar_t>
{
inline FString(){}
FString(const wchar_t* other)
{
Max = Count = *other ? std::wcslen(other) + 1 : 0;
if (Count)
{
Data = const_cast<wchar_t*>(other);
}
};
inline bool IsValid() const
{
return Data != nullptr;
}
inline const wchar_t* c_str() const
{
return Data;
}
std::string ToString() const
{
auto length = std::wcslen(Data);
std::string str(length, '\0');
std::use_facet<std::ctype<wchar_t>>(std::locale()).narrow(Data, Data + length, '?', &str[0]);
return str;
}
};
void CallExecuteUIEvent(int eventID, const wchar_t* strParam)
{
FString param(strParam);
fExecuteUIEvent(fGetXMLUIManagerPtr(), eventID, ¶m);
}
Да спасибо помог все работает!Fyyre и акуму заливали сдк для грации и интерлюда, там это есть. Точно уже не вспомню чью работу я взял себе (мне нужен был только FString)
Hello CharmantFyyre and akuma were poured with SDK for grace and interlude, there it is. I don't remember exactly whose job I took for myself (I only needed FString)
I use it for events like this:
C++:void CallExecuteUIEvent(int eventID, const wchar_t* strParam) { FString param(strParam); fExecuteUIEvent(fGetXMLUIManagerPtr(), eventID, ¶m); }
Нужно найти оффсет XMLUIManager в nwindow.dll, он отличается в разных версиях клиента. Дальше всё просто:code you used to get pointer to IUManager?
uintptr_t XMLUIPtrOffset = 0x1100; // gracia epilogue
uintptr_t nwindowBaseAddr = 0;
GetXMLUIManager_fn fGetXMLUIManagerPtr = nullptr;
typedef int(__fastcall* GetXMLUIManager_fn)();
// nwindowBaseAddr уже получен, !=0
fGetXMLUIManagerPtr = (GetXMLUIManager_fn)(nwindowBaseAddr + XMLUIPtrOffset);
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?