@
Raistlin
To add to what igrik posted while I was typing this...
Don't use inline ASM to acquire registers unless you declare the function
__declspec(naked), you never know how compiler will act exactly.
However if you do declare it __declspec(naked) then you have to handle all of the stack yourself, not the most intuitive when working with LoHook. (So best thing, avoid assembly whenever possible)
The guaranteed safe way to do your way with C++ and the LoHook function would be:
Code:
//THISCALL_6(void, 0x4136F0, c->edi, 1, 1, 0, 0, 0);
CALL_6(void, __thiscall, 0x4136F0, c->edi, 1, 1, 0, 0, 0);
Or use igrik's version
Or add it as a member function of AdvMgr and use it directly... AdvMgr->UpdateScreen();
However there is another issue in this code, by jumping to 0x41D474 you are skipping over
Which means you are not restoring EDI which was pushed on stack at 0x41D232; this is highly likely to cause all sorts of problems including crashes.
Code:
int __stdcall DisableManaUsage(LoHook* hook, HookContext* c)
{
/* insert update screen code */
c->edi = c->Pop(); // missing line, pop the top stack value back to edi
c->return_address = 0x41D474;
return NO_EXEC_DEFAULT;
}
@
igrik
As we previously discussed, you can create your own custom format that inherits from an existing control, and do two modifications:
1- add a DlgItem* field (linkedItem) to link it with the control beneath it
2- modify the virtual table with your own by changing the ProcessMsg(H3Msg& msg) function (+08) with your own.
This can be accomplished either by properly writing virtual function for all controls or using similar style to Wog dialogs / Baratorch dialogs of creating a custom virtual table and inserting it after the control is created (effectively more C-style).
C++style
Code:
struct MyCustomControl : DlgItem
{
DlgItem* linkedControl;
virtual int ProcessMsg(H3Msg& msg) override
{
if (linkedControl)
return linkedControl->ProcessMsg(msg);
return 2; // stop processing the current msg
return THISCALL_2(int, /*insert_original_address*/, this, &msg); // call original message process
};
// add in constructor etc.
};
C-style
Code:
struct MyCustomControl : DlgItem
{
DlgItem* linkedControl;
// add in constructor etc.
static int __fastcall CustomProcessMsg(MyCustomControl* control, int unused, H3Msg& msg)
{
if (control->linkedItem) // can add some more checks if needed
return control->linkedItem->ProcessMsg(msg);
return 2; // stop processing the current msg
return THISCALL_2(int, /*insert_original_address*/, control, &msg); // call original message process
}
static int customVT[] = {
0x123456, // use the actual function addresses
0x222222,
(int)MyCustomControl::CustomProcessMsg,
0xABCDEF,
...
};
}
...and set custom virtual table after creation...
Code:
MyCustomControl* customControl = new MyCustomControl(.......) (in whatever way you pick to create it)
*(int*)(customControl) = (int)MyCustomControl::customVT; // set new virtual table
Whichever way you pick, anytime you perform an action on the overlaying transparent control the message is instead transferred to the linked control.
###
Making properly overloaded controls is, imo, easier, more versatile and does not take a considerable amount of time really since you can simply make a virtual function call the original one. Something I am planning to add in the api when I get time...