Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

[Release]GMSv83 Outlink and Inlink Support

Newbie Spellweaver
Joined
Mar 26, 2020
Messages
50
Reaction score
13
Hello everyone, below is the code for GMSv83 that I researched earlier, which supports outlink and inlink.There may be some shortcomings in it, and I am sharing it here.I hope someone can join me in improving it


C++:
#include <OAIdl.h>
#include "inlink_outlink_fix.h"
#include <memory>
#include <string>
#include <map>
#include <algorithm>

typedef int(__stdcall* IWzGr2D__GetLayer_t)(DWORD*, VARIANTARG, DWORD**);
typedef int(__stdcall* IWzVector2D__RelMove_t)(DWORD*, int, int, VARIANTARG, VARIANTARG);
typedef int(__stdcall* IWzCanvas_PutCXY_t)(DWORD*, int);
typedef void(__thiscall* _CCtrlButton__SetEnable)(DWORD*, void*, int);

#define IWzGr2DLayer__Getcanvas(x, r) (*(IWzGr2D__GetLayer_t*)(*(DWORD*)(x) + 256))((DWORD *)x, pvarg, r)
#define IWzVector2D__RelMove(x, l, t) (*(IWzVector2D__RelMove_t*)(*(DWORD*)(x) + 144))((DWORD *)x, l, t, errorVar, errorVar)
#define GET_IWzVector2D(x) (sp[x][6])
#define CCtrlButton__SetEnable(x, nEnable) (*(_CCtrlButton__SetEnable*)(*(*(*((DWORD***)(x)) + 4) + 28)))(*((DWORD**)(x)) + 4, nullptr, nEnable);

typedef int* (__fastcall* _CWnd__CreateWnd)(DWORD* This, void* notuse, int nLeft, int nTop,
    int nWidth, int nHeight, int z, int bScreenCoord, DWORD* pData, int bSetFocus);

typedef int(__fastcall* _bstr_constructor)(void* ecx, void* edx, const char* str);
typedef int(__fastcall* _bstr_constructor_wchar)(void* ecx, void* edx, const wchar_t* str);
typedef int(__fastcall* _bstr_release)(void* ecx, void* edx);
typedef DWORD* (__fastcall* _ZXString_char_constructor)(void* ecx, void* edx, const char*, size_t);

typedef int(__fastcall* _IWzProperty_QueryInterface)(IUnknown** This, void* notuse, IUnknown* a2);
typedef DWORD(__fastcall* _Ztl_variant_t__GetUnknown)(VARIANTARG* This, void* notuse, bool a2, bool a3);
typedef DWORD(__fastcall* _IWzCanvas__GetProperty)(DWORD* This, void* notuse, IUnknown** a2);
typedef VARIANTARG* (__fastcall* _IWzProperty__GetItem)(IUnknown* This, void* notuse, VARIANTARG* pvargDest, int* sPath);
typedef int(__fastcall* _IWzUOL__GetfilePath)(DWORD* This, void* notuse, int a2);
typedef IUnknown* (__fastcall* _IWzUOL_QueryInterface)(DWORD* This, void* notuse, IUnknown* a2);
typedef VARIANTARG* (__fastcall* _IWzResMan__GetObjectA)(DWORD* This, void* notuse, VARIANTARG* pvargDest, int* sUOL, int vParam, int vAux);
typedef DWORD* (__cdecl* _get_unknown)(DWORD*, VARIANT*);
typedef int(__fastcall* _IWzCanvas_operator_equal)(DWORD* This, void* notuse, DWORD* a2);
typedef int(__fastcall* _CWndMan__EnableIME)(DWORD* This, void* notuse, int bEnable);
typedef void(__fastcall* _CCtrlEdit__SetText)(DWORD* This, void* notuse, char* a2);
typedef void(__fastcall* _CWvsApp__CreateMainWindow)(DWORD* This, void* notuse);
typedef int(__fastcall* _IWzCanvas__Getwidth)(DWORD* This, void* notuse);
typedef int(__fastcall* _IWzCanvas__Getheight)(DWORD* This, void* notuse);
typedef DWORD* (__fastcall* _IWzCanvas__DrawTextA)(DWORD* This, void* notuse, int nLeft, int nTop, int* sText, int pFont, DWORD* vAlpha, DWORD* vTabOrg);

VARIANTARG errorVar = { VT_ERROR, 0, 0, 0x80020004 };
VARIANTARG pvarg = { VT_I4, 0, 0, 0 };
VARIANTARG pvargSrc = { 0 };

_CWnd__CreateWnd CWnd__CreateWnd = (_CWnd__CreateWnd)0x9DE4D2;

_bstr_constructor bstr_constructor = (_bstr_constructor)0x406301;
_bstr_constructor_wchar bstr_constructor_wchar = (_bstr_constructor_wchar)0x402BE8;
_bstr_release bstr_release = (_bstr_release)0x402EA5;
_ZXString_char_constructor ZXString_char_constructor = (_ZXString_char_constructor)0x428DB3;

_IWzProperty_QueryInterface IWzProperty_QueryInterface = (_IWzProperty_QueryInterface)0x4052AD;
_Ztl_variant_t__GetUnknown Ztl_variant_t__GetUnknown = (_Ztl_variant_t__GetUnknown)0x4032B2;
_IWzCanvas__GetProperty IWzCanvas__GetProperty = (_IWzCanvas__GetProperty)0x404AD7;
_IWzProperty__GetItem IWzProperty__GetItem = (_IWzProperty__GetItem)0x403935;
_IWzUOL__GetfilePath IWzUOL__GetfilePath = (_IWzUOL__GetfilePath)0x414C70;
_IWzUOL_QueryInterface IWzUOL_QueryInterface = (_IWzUOL_QueryInterface)0x416838;
_IWzResMan__GetObjectA IWzResMan__GetObjectA = (_IWzResMan__GetObjectA)0x403A93;

_get_unknown get_unknown = (_get_unknown)0x414ADA;
_IWzCanvas_operator_equal IWzCanvas_operator_equal = (_IWzCanvas_operator_equal)0x41E42B;

_CWndMan__EnableIME CWndMan__EnableIME = (_CWndMan__EnableIME)0x9E85F3;
_CCtrlEdit__SetText CCtrlEdit__SetText = (_CCtrlEdit__SetText)0x4CC512;

_CWvsApp__CreateMainWindow CWvsApp__CreateMainWindow = (_CWvsApp__CreateMainWindow)0x9F6D97;

_IWzCanvas__Getwidth IWzCanvas__Getwidth = (_IWzCanvas__Getwidth)0x40B920;
_IWzCanvas__Getheight IWzCanvas__Getheight = (_IWzCanvas__Getheight)0x40B947;
_IWzCanvas__DrawTextA IWzCanvas__DrawTextA = (_IWzCanvas__DrawTextA)0x4277AD;

void** g_gr = (void**)0xBF14EC;
void** g_rm = (void**)0xBF14E8;
void** g_wvsapp = (void**)0xBE7B38;
void** g_wndman = (void**)0xBEC20C;
void** g_uistatusbar = (void**)0xBEC208;
void** g_actionman = (void**)0xBE78D4;


DWORD* GetCWvsAppInstance()
{
    return (DWORD*)*g_wvsapp;
}

HWND GetMapleMainWindow()
{
    return (HWND) * (GetCWvsAppInstance() + 1);
}

DWORD* GetGr2DInstance()
{
    return (DWORD*)*g_gr;
}

DWORD* GetCWndManInstance()
{
    return (DWORD*)*g_wndman;
}

DWORD* GetUIStatusBarInstance()
{
    return (DWORD*)*g_uistatusbar;
}

DWORD* GetResManInstance()
{
    return (DWORD*)*g_rm;
}


DWORD* GetActionManInstance()
{
    return (DWORD*)*g_actionman;
}

std::map<IUnknown*, std::shared_ptr<std::wstring>> gMapImgPath;
void* GetUOLProperty(VARIANT* prop, void** result)
{
    if (prop == NULL || result == NULL)
        return NULL;
    IUnknown* pUnk = (IUnknown*)Ztl_variant_t__GetUnknown(prop, nullptr, 0, 0);
    if (pUnk)
    {
        pUnk->AddRef();
        IUnknown* pWzUOL = NULL;

        IWzUOL_QueryInterface((DWORD*)&pWzUOL, nullptr, (IUnknown*)&pUnk);

        if (pWzUOL)
        {
            IWzUOL__GetfilePath((DWORD*)pWzUOL, nullptr, (int)result);
            if (*result)
                return *result;
        }
    }
    return NULL;
}

std::wstring GetImgFullPath(std::wstring strT)
{
    std::wstring lstr = strT;
    std::transform(lstr.begin(), lstr.end(), lstr.begin(), towlower);

    int pos = lstr.rfind(L".img");
    if (pos != std::string::npos)
    {
        pos += 4; // 4
        strT = strT.substr(0, pos);
        strT += L"/";
    }
    return strT;
}

DWORD GetCanvasPropertyByPath(std::wstring path, DWORD* result)
{
    VARIANT varDest = { 0 };
    VARIANT var1 = { 0 };
    VARIANT var2 = { 0 };
    DWORD varUnk = 0;
    void* sUol = NULL;
    bstr_constructor_wchar(&sUol, nullptr, path.c_str());
    auto v9 = IWzResMan__GetObjectA((DWORD*)*g_rm, nullptr, &varDest, (int*)sUol, (int)&var1, (int)&var2);
    auto v10 = get_unknown(&varUnk, v9);
    return IWzCanvas_operator_equal(result, nullptr, v10);
}

int __fastcall IWzCanvas_operator_equal_Hook(DWORD* This, void* notuse, DWORD* a2)
{
    auto ret = IWzCanvas_operator_equal(This, nullptr, a2);
    IUnknown* prop = NULL;
    void* pStrInlink = NULL;
    void* pStrOutlink = NULL;
    VARIANT dst = { 0 };
    int w = 0, h = 0;
    if (!*This)
        goto RET;

    w = IWzCanvas__Getwidth((DWORD*)*This, nullptr);
    h = IWzCanvas__Getheight((DWORD*)*This, nullptr);

    if (w > 1 || h > 1)
        goto RET;

    IWzCanvas__GetProperty((DWORD*)*This, nullptr, &prop);

    if (!prop)
        goto RET;

    bstr_constructor(&pStrInlink, nullptr, "_inlink");

    if (!pStrInlink)
        goto OUTLINK;

    IWzProperty__GetItem(prop, nullptr, &dst, (int*)pStrInlink);

    if (!dst.vt)
        goto OUTLINK;

    if (dst.vt == VT_BSTR)
    {
        void* link = NULL;
        if (dst.bstrVal)
        {
            IUnknown* pUnk = (IUnknown*)*a2;

            if (gMapImgPath.find(pUnk) != gMapImgPath.end())
            {
                //LOGI("_inlink: %S, FullPath: %S", dst.bstrVal, gMapImgPath[pUnk]->c_str());
                DWORD ptr = 0;
                ret = GetCanvasPropertyByPath(GetImgFullPath(gMapImgPath[pUnk]->c_str()) + dst.bstrVal, (DWORD*)&ptr);
                if (ptr)
                    *This = ptr;
            }
        }
    }

OUTLINK:
    bstr_constructor(&pStrOutlink, nullptr, "_outlink");
    IWzProperty__GetItem(prop, nullptr, &dst, (int*)pStrOutlink);

    if (!dst.vt)
        goto RET;

    if (dst.vt == VT_BSTR)
    {
        void* link = NULL;
        if (dst.bstrVal)
        {
            DWORD ptr = 0;
            ret = GetCanvasPropertyByPath(dst.bstrVal, (DWORD*)&ptr);
            if (ptr)
                *This = ptr;
        }
    }


RET:
    if (prop)
        ((IUnknown*)prop)->Release();
    return ret;
};

 VARIANTARG* __fastcall IWzResMan__GetObjectA_Hook(DWORD* This, void* notuse, VARIANTARG* pvargDest, int* sUOL, int vParam, int vAux)
{
    std::wstring strT = (wchar_t*)*sUOL;
    auto ret = IWzResMan__GetObjectA(This, nullptr, pvargDest, sUOL, vParam, vAux);
    if (ret && ret->vt == VT_UNKNOWN)
    {
        gMapImgPath[ret->punkVal] = std::make_shared<std::wstring>(strT);
    }
    return ret;
};

 VARIANTARG* __fastcall IWzProperty__GetItem_Hook(IUnknown* This, void* notuse, VARIANTARG* pvargDest, int* sPath)
{
    std::wstring strT = (wchar_t*)*sPath;
    auto ret = IWzProperty__GetItem(This, nullptr, pvargDest, sPath);
    if (pvargDest->vt == VT_UNKNOWN)
    {
        if (gMapImgPath.find(This) != gMapImgPath.end())
        {
            gMapImgPath[pvargDest->punkVal] = gMapImgPath[This];
        }
    }
    void* sUOL = NULL;
    GetUOLProperty(pvargDest, &sUOL);
    if (sUOL)
    {
        VARIANTARG pvarg1 = errorVar;
        VARIANTARG pvarg2 = errorVar;
        ret = IWzResMan__GetObjectA(GetResManInstance(), nullptr, pvargDest, (int*)sUOL, (int)&pvarg1, (int)&pvarg2);
    }
    return ret;
};

void InitInlinkOutlink()
{
    SetHook(true, reinterpret_cast<void**>(&IWzProperty__GetItem), IWzProperty__GetItem_Hook);
    SetHook(true, reinterpret_cast<void**>(&IWzResMan__GetObjectA), IWzResMan__GetObjectA_Hook);
    SetHook(true, reinterpret_cast<void**>(&IWzCanvas_operator_equal), IWzCanvas_operator_equal_Hook);
}
 
Newbie Spellweaver
Joined
Jun 21, 2019
Messages
7
Reaction score
0
Hello sir, can you tell me how can i get inlink_outlink_fix.h file?
 
Newbie Spellweaver
Joined
Jul 31, 2023
Messages
19
Reaction score
5
hi thanks for sharing. sorry if noob question but how would i implement this code? i currently am using ezorsia. do i create a inlink_outlink_fix.cpp file and paste this code in there?
 
Back
Top