Как вернуть строку из DLL C++ в UnrealScript?

BIT_hack

Знающий
Участник
Сообщения
254
Розыгрыши
0
Решения
2
Репутация
79
Реакции
158
Баллы
485
Как можно вернуть строку из DLL C++ в UnrealScript, не используя сторонние библиотек?
Я пробую так и еще 1000 способов но постоянно получаю ошибку связанную с FArray



C++ (.*dll)
C++:
// Класс-заглушка
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;
}

UnrealScript (.*uc)
C-подобный:
native(1255) final function string GetMyString(); 

AddSystemMessageString("DLL_TEXT="@GetMyString()); //string Вывод системных сообщений в чат
 
реализовать класс FString. Он имеет не просто массив байт но и размер и важно использовать менеджер памяти клиента для создания/удаления строки.
 
Могли бы вы привести пример, я пока не понимаю как это работает(
 
Хорошо, спасибо, я понял. Буду разбираться. Буду очень признателен, если кто-то сможет дать мне более подробные разъяснения.
 
Могли бы вы привести пример, я пока не понимаю как это работает(
Fyyre и акуму заливали сдк для грации и интерлюда, там это есть. Точно уже не вспомню чью работу я взял себе (мне нужен был только FString)
C++:
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;
    }
};

Использую для ивентов так:
C++:
void CallExecuteUIEvent(int eventID, const wchar_t* strParam)
{
    FString param(strParam);
    fExecuteUIEvent(fGetXMLUIManagerPtr(), eventID, &param);
}
 
Да спасибо помог все работает!
 
Hello Charmant

Can you post here code you used to get pointer to IUManager?
Thank you in advance
 
code you used to get pointer to IUManager?
Нужно найти оффсет XMLUIManager в nwindow.dll, он отличается в разных версиях клиента. Дальше всё просто:
C++:
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);