• Unfortunately, we have experienced significant hard drive damage that requires urgent maintenance and rebuilding. The forum will be a state of read only until we install our new drives and rebuild all the configurations needed. Please follow our Facebook page for updates, we will be back up shortly! (The forum could go offline at any given time due to the nature of the failed drives whilst awaiting the upgrades.) When you see an Incapsula error, you know we are in the process of migration.

[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