diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b2a1e47..c0ebc36 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,11 +18,11 @@ jobs: ref: master build: - os: ubuntu-latest - container: ghcr.io/alliedmodders/build-containers/debian11:latest + container: ghcr.io/alliedmodders/build-containers/debian11-clang22:latest target: x86 platform: linux32 - os: ubuntu-latest - container: ghcr.io/alliedmodders/build-containers/debian11:latest + container: ghcr.io/alliedmodders/build-containers/debian11-clang22:latest target: x86_64 platform: linux64 - os: windows-latest diff --git a/AMBuildScript b/AMBuildScript index ac071ab..17bf812 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -249,6 +249,11 @@ class ExtensionConfig(object): '-Wno-tautological-overlap-compare', ] + if cxx.version >= 'clang-16.0': + cxx.cxxflags += [ + '-Wno-nontrivial-memcall', + ] + if have_gcc: cxx.cflags += ['-mfpmath=sse'] cxx.cflags += ['-Wno-maybe-uninitialized'] @@ -360,6 +365,10 @@ class ExtensionConfig(object): os.path.join(self.mms_root, 'core', 'sourcehook'), ] + khook_include = os.path.join(self.mms_root, 'third_party', 'khook', 'include') + if os.path.isdir(khook_include): + compiler.cxxincludes += [khook_include] + for other_sdk in self.sdk_manifests: compiler.defines += ['SE_{}={}'.format(other_sdk['define'], other_sdk['code'])] diff --git a/src/extension.cpp b/src/extension.cpp index f484324..987d844 100644 --- a/src/extension.cpp +++ b/src/extension.cpp @@ -3,15 +3,17 @@ #include "script_context.h" #include "callback_manager.h" +#include + CVScriptExtension g_VScriptExt; CGlobalVars *gpGlobals = nullptr; uint32_t g_vmGeneration = 0; SMEXT_LINK(&g_VScriptExt); -SH_DECL_HOOK1(IScriptManager, CreateVM, SH_NOATTRIB, 0, IScriptVM *, ScriptLanguage_t); -SH_DECL_HOOK1_void(IScriptManager, DestroyVM, SH_NOATTRIB, 0, IScriptVM *); -SH_DECL_HOOK1(IScriptVM, RegisterClass, SH_NOATTRIB, 0, bool, ScriptClassDesc_t *); -SH_DECL_HOOK1_void(IScriptVM, SetErrorCallback, SH_NOATTRIB, 0, ScriptErrorFunc_t); +static KHook::Virtual g_HookCreateVM; +static KHook::Virtual g_HookDestroyVM; +static KHook::Virtual g_HookRegisterClass; +static KHook::Virtual g_HookSetErrorCallback; static void OnScriptOutput(const char *pszText) { @@ -41,49 +43,99 @@ static bool OnScriptError(ScriptErrorLevel_t eLevel, const char *pszText) return false; } -void CVScriptExtension::Hook_SetErrorCallback(ScriptErrorFunc_t pFunc) +KHook::Return CVScriptExtension::Hook_CreateVM(IScriptManager *pManager, ScriptLanguage_t language) +{ + IScriptVM *pVM = g_HookCreateVM.CallOriginal(pManager, language); + OnVMCreated(pVM); + return {KHook::Action::Supersede, pVM}; +} + +KHook::Return CVScriptExtension::Hook_DestroyVM(IScriptManager *pManager, IScriptVM *pVM) +{ + OnVMDestroyed(pVM); + g_HookDestroyVM.CallOriginal(pManager, pVM); + OnVMDestroyedPost(); + return {KHook::Action::Supersede}; +} + +KHook::Return CVScriptExtension::Hook_RegisterClass(IScriptVM *pVM, ScriptClassDesc_t *pClassDesc) +{ + g_CallbackManager.OnRegisterClass(pClassDesc); + return {KHook::Action::Ignore}; +} + +KHook::Return CVScriptExtension::Hook_SetErrorCallback(IScriptVM *pVM, ScriptErrorFunc_t pFunc) { g_pOriginalErrorCallback = pFunc; - SH_CALL(m_pScriptVM, &IScriptVM::SetErrorCallback)(&OnScriptError); - RETURN_META(MRES_SUPERCEDE); + g_HookSetErrorCallback.CallOriginal(pVM, &OnScriptError); + return {KHook::Action::Supersede}; } -IScriptVM *CVScriptExtension::Hook_CreateVM(ScriptLanguage_t language) +void CVScriptExtension::InstallManagerHooks() { - IScriptVM *pVM = META_RESULT_ORIG_RET(IScriptVM *); + g_HookCreateVM.AddContext(this, &CVScriptExtension::Hook_CreateVM, nullptr); + g_HookCreateVM.Configure(&IScriptManager::CreateVM); - if (pVM) - { - SetCurrentVM(pVM); + g_HookDestroyVM.AddContext(this, &CVScriptExtension::Hook_DestroyVM, nullptr); + g_HookDestroyVM.Configure(&IScriptManager::DestroyVM); - SH_ADD_HOOK(IScriptVM, RegisterClass, pVM, SH_MEMBER(this, &CVScriptExtension::Hook_RegisterClass), false); - SH_ADD_HOOK(IScriptVM, SetErrorCallback, pVM, SH_MEMBER(this, &CVScriptExtension::Hook_SetErrorCallback), false); + g_HookRegisterClass.AddContext(this, &CVScriptExtension::Hook_RegisterClass, nullptr); + g_HookRegisterClass.Configure(&IScriptVM::RegisterClass); - pVM->SetOutputCallback(&OnScriptOutput); - SH_CALL(pVM, &IScriptVM::SetErrorCallback)(&OnScriptError); // bypass hook + g_HookSetErrorCallback.AddContext(this, &CVScriptExtension::Hook_SetErrorCallback, nullptr); + g_HookSetErrorCallback.Configure(&IScriptVM::SetErrorCallback); - if (m_pOnVMInit) - m_pOnVMInit->Execute(nullptr); + g_HookCreateVM.Add(m_pScriptManager); + g_HookDestroyVM.Add(m_pScriptManager); +} - g_CallbackManager.OnVMInitialized(pVM); +void CVScriptExtension::RemoveManagerHooks() +{ + if (m_pScriptManager) + { + g_HookCreateVM.Remove(m_pScriptManager); + g_HookDestroyVM.Remove(m_pScriptManager); } +} - RETURN_META_VALUE(MRES_IGNORED, pVM); +void CVScriptExtension::InstallVMHooks(IScriptVM *pVM) +{ + g_HookRegisterClass.Add(pVM); + g_HookSetErrorCallback.Add(pVM); } -bool CVScriptExtension::Hook_RegisterClass(ScriptClassDesc_t *pClassDesc) +void CVScriptExtension::RemoveVMHooks() { - g_CallbackManager.OnRegisterClass(pClassDesc); + if (m_pScriptVM) + { + g_HookRegisterClass.Remove(m_pScriptVM); + g_HookSetErrorCallback.Remove(m_pScriptVM); + } +} + +void CVScriptExtension::OnVMCreated(IScriptVM *pVM) +{ + if (!pVM) + return; + + m_pScriptVM = pVM; + + InstallVMHooks(pVM); + + pVM->SetOutputCallback(&OnScriptOutput); + g_HookSetErrorCallback.CallOriginal(pVM, &OnScriptError); - RETURN_META_VALUE(MRES_IGNORED, true); + if (m_pOnVMInit) + m_pOnVMInit->Execute(nullptr); + + g_CallbackManager.OnVMInitialized(pVM); } -void CVScriptExtension::Hook_DestroyVM(IScriptVM *pVM) +void CVScriptExtension::OnVMDestroyed(IScriptVM *pVM) { if (pVM && pVM == m_pScriptVM) { - SH_REMOVE_HOOK(IScriptVM, RegisterClass, pVM, SH_MEMBER(this, &CVScriptExtension::Hook_RegisterClass), false); - SH_REMOVE_HOOK(IScriptVM, SetErrorCallback, pVM, SH_MEMBER(this, &CVScriptExtension::Hook_SetErrorCallback), false); + RemoveVMHooks(); g_pOriginalErrorCallback = nullptr; g_CallbackManager.OnVMShutdown(); @@ -95,14 +147,11 @@ void CVScriptExtension::Hook_DestroyVM(IScriptVM *pVM) SetCurrentVM(nullptr); } - - RETURN_META(MRES_IGNORED); } -void CVScriptExtension::Hook_DestroyVM_Post(IScriptVM *pVM) +void CVScriptExtension::OnVMDestroyedPost() { g_CallbackManager.CleanupStaleRegistrations(); - RETURN_META(MRES_IGNORED); } bool CVScriptExtension::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late) @@ -111,28 +160,16 @@ bool CVScriptExtension::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t max GET_V_IFACE_CURRENT(GetEngineFactory, m_pScriptManager, IScriptManager, VSCRIPT_INTERFACE_VERSION); - SH_ADD_HOOK(IScriptManager, CreateVM, m_pScriptManager, SH_MEMBER(this, &CVScriptExtension::Hook_CreateVM), true); - SH_ADD_HOOK(IScriptManager, DestroyVM, m_pScriptManager, SH_MEMBER(this, &CVScriptExtension::Hook_DestroyVM), false); - SH_ADD_HOOK(IScriptManager, DestroyVM, m_pScriptManager, SH_MEMBER(this, &CVScriptExtension::Hook_DestroyVM_Post), true); + InstallManagerHooks(); return true; } bool CVScriptExtension::SDK_OnMetamodUnload(char *error, size_t maxlen) { - if (m_pScriptVM) - { - SH_REMOVE_HOOK(IScriptVM, RegisterClass, m_pScriptVM, SH_MEMBER(this, &CVScriptExtension::Hook_RegisterClass), false); - SH_REMOVE_HOOK(IScriptVM, SetErrorCallback, m_pScriptVM, SH_MEMBER(this, &CVScriptExtension::Hook_SetErrorCallback), false); - g_pOriginalErrorCallback = nullptr; - } - - if (m_pScriptManager) - { - SH_REMOVE_HOOK(IScriptManager, CreateVM, m_pScriptManager, SH_MEMBER(this, &CVScriptExtension::Hook_CreateVM), true); - SH_REMOVE_HOOK(IScriptManager, DestroyVM, m_pScriptManager, SH_MEMBER(this, &CVScriptExtension::Hook_DestroyVM), false); - SH_REMOVE_HOOK(IScriptManager, DestroyVM, m_pScriptManager, SH_MEMBER(this, &CVScriptExtension::Hook_DestroyVM_Post), true); - } + RemoveVMHooks(); + g_pOriginalErrorCallback = nullptr; + RemoveManagerHooks(); return true; } diff --git a/src/extension.h b/src/extension.h index 312c854..07d9be9 100644 --- a/src/extension.h +++ b/src/extension.h @@ -74,6 +74,10 @@ class CVScriptExtension IForward *GetOnScriptPrintForward() const { return m_pOnScriptPrint; } IForward *GetOnScriptErrorForward() const { return m_pOnScriptError; } + void OnVMCreated(IScriptVM *pVM); + void OnVMDestroyed(IScriptVM *pVM); + void OnVMDestroyedPost(); + private: IScriptManager *m_pScriptManager = nullptr; IScriptVM *m_pScriptVM = nullptr; @@ -99,11 +103,15 @@ class CVScriptExtension void SetCurrentVM(IScriptVM *pVM); - IScriptVM *Hook_CreateVM(ScriptLanguage_t language); - void Hook_DestroyVM(IScriptVM *pVM); - void Hook_DestroyVM_Post(IScriptVM *pVM); - bool Hook_RegisterClass(ScriptClassDesc_t *pClassDesc); - void Hook_SetErrorCallback(ScriptErrorFunc_t pFunc); + void InstallManagerHooks(); + void RemoveManagerHooks(); + void InstallVMHooks(IScriptVM *pVM); + void RemoveVMHooks(); + + KHook::Return Hook_CreateVM(IScriptManager *pManager, ScriptLanguage_t language); + KHook::Return Hook_DestroyVM(IScriptManager *pManager, IScriptVM *pVM); + KHook::Return Hook_RegisterClass(IScriptVM *pVM, ScriptClassDesc_t *pClassDesc); + KHook::Return Hook_SetErrorCallback(IScriptVM *pVM, ScriptErrorFunc_t pFunc); }; void ReleaseOwnedHScript(IScriptVM *pVM, HSCRIPT hScript, HScriptType type);