From 3ddc62cf61138cea7421a4fd4c9a4bf1f16919b2 Mon Sep 17 00:00:00 2001 From: llde Date: Sat, 16 Sep 2023 00:35:22 +0200 Subject: [PATCH] Better Hook for script error messages. Close #220 --- obse/obse/Hooks_Script.cpp | 92 +++++++++++++++++++++++++------------- 1 file changed, 62 insertions(+), 30 deletions(-) diff --git a/obse/obse/Hooks_Script.cpp b/obse/obse/Hooks_Script.cpp index d40e9dc..c564096 100644 --- a/obse/obse/Hooks_Script.cpp +++ b/obse/obse/Hooks_Script.cpp @@ -13,6 +13,7 @@ char s_ExpressionParserAltBuffer[0x500] = {0}; #if OBLIVION #include "StringVar.h" +#include const UInt32 ExtractStringPatchAddr = 0x004FB1EB; const UInt32 ExtractStringRetnAddr = 0x004FB1F4; @@ -40,6 +41,8 @@ static const UInt32 kScriptRunner_RunRetnAddr = kScriptRunner_RunHookAddr + 5; static const UInt32 kScriptRunner_RunCallAddr = 0x005792E0; // overwritten call static const UInt32 kScriptRunner_RunEndProcAddr = 0x00517637; // retn 0x20 static const UInt32 kScriptRunner_CommandResult = 0x0051757B; +static constexpr UInt32 kReturnCmdExecute = 0x005169B4; +static constexpr UInt32 kReturnCmdHook = 0x005169AE; static void __stdcall DoExtractString(char* scriptData, UInt32 dataLen, char* dest, ScriptEventList* eventList) @@ -127,43 +130,65 @@ static __declspec(naked) void ExpressionParserBufferOverflowHook_2(void) } } -std::string Message = ""; - -static void LogScriptError(Script* faultScript) { - size_t pos = Message.rfind("\r\n"); - if (pos != std::string::npos) { - _MESSAGE("%u %s ", pos, Message.c_str()); - Message = Message.substr(0, pos); +Script* boh; +static void LogScriptError(const char* Format, va_list ArgList){ + char DestBuf[13000]; + if (boh) { + vsprintf_s(DestBuf, Format, ArgList); + ShowRuntimeError(boh, DestBuf); + boh = nullptr; } - ShowRuntimeError(faultScript, Message.c_str()); - Message = ""; } -void __declspec(naked) ScriptRunnerLineExecutionFailedHook(void) -{ - __asm - { - cmp [esp + 0x16], 0 - jz normal +void __declspec(naked) Script_ExecuteCommandHook1() { + __asm { + sub esp, 0x73C + mov eax, [esp + 0x748 + 4] + mov boh, eax + jmp [kReturnCmdExecute] + } +} - mov edi, [esp + 0x770] - pushad - call LogScriptError - popad +//Take address dynamically to address for MessagELogger hooks//Take address dynamically to address for MessagELogger hooks +int(__cdecl* MessageHandler_HandleMessage)(int, char*, va_list) = nullptr; - - normal: - mov ecx, 0x00517582 - cmp [esp + 0x780], bl - jmp ecx +int __declspec(naked) PrintScriptErrorJmp(char* Format, ...) +{ + __asm { + mov ecx, [esp + 0x4] + lea eax, [esp + 0x8] + push eax + push ecx + call LogScriptError + pop ecx + pop eax + push eax; ArgList + push ecx; Format + push 3; + jmp MessageHandler_HandleMessage + add esp, 0Ch + retn } } - -static void WINAPI DetourErrorMessage(const char* Messaged) { - Message = Messaged; +int __declspec(naked) PrintScriptErrorCall(char* Format, ...) +{ + __asm { + mov ecx, [esp + 0x4] + lea eax, [esp + 0x8] + push eax + push ecx + call LogScriptError + pop ecx + pop eax + push eax; ArgList + push ecx; Format + push 3; + call MessageHandler_HandleMessage + add esp, 0Ch + retn + } } - void Hook_Script_Init() { WriteRelJump(ExtractStringPatchAddr, (UInt32)&ExtractStringHook); @@ -186,8 +211,15 @@ void Hook_Script_Init() // hook ExtractArgs() to handle commands normally compiled with Cmd_Default_Parse which were instead compiled with Cmd_Expression_Parse ExtractArgsOverride::Init_Hooks(); - WriteRelJump(kScriptRunner_CommandResult, (UInt32)&ScriptRunnerLineExecutionFailedHook); - SafeWrite32(0x00A3DA0C, (UInt32) &DetourErrorMessage); + //PAtch PrintError in Command_Execute. Get dynamically address destination to address for MessageLogger + MessageHandler_HandleMessage = (int(__cdecl*)(int, char*, va_list)) (*(UInt32*)(0x004A7A6C + 1) + 0x004A7A6C + 1 + 4); + if (*(UInt8*)0x004A7A6C == 0xE9) { + PatchCallsInRange(0x005169A0, 0x0051722B, 0x004A7A60, (UInt32)&PrintScriptErrorJmp); + } + else { + PatchCallsInRange(0x005169A0, 0x0051722B, 0x004A7A60, (UInt32)&PrintScriptErrorCall); + } + WriteRelJump(kReturnCmdHook, (UInt32)& Script_ExecuteCommandHook1); } void ResetActivationRecurseDepth()