diff --git a/AMBuildScript b/AMBuildScript index 2e5a74b..74f49b6 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -16,9 +16,9 @@ class MMS: self.sdkInfo['ep2v'] = {'sdk': 'HL2SDKOBVALVE', 'ext': '2.ep2v', 'def': '4', 'name': 'ORANGEBOXVALVE', 'platform': ['windows', 'linux', 'darwin']} self.sdkInfo['l4d'] = {'sdk': 'HL2SDKL4D', 'ext': '2.l4d', 'def': '5', - 'name': 'LEFT4DEAD', 'platform': ['windows', 'linux']} + 'name': 'LEFT4DEAD', 'platform': ['windows', 'linux', 'darwin']} self.sdkInfo['l4d2'] = {'sdk': 'HL2SDKL4D2', 'ext': '2.l4d2', 'def': '6', - 'name': 'LEFT4DEAD2', 'platform': ['windows', 'linux']} + 'name': 'LEFT4DEAD2', 'platform': ['windows', 'linux', 'darwin']} self.sdkInfo['darkm'] = {'sdk': 'HL2SDK-DARKM', 'ext': '2.darkm', 'def': '2', 'name': 'DARKMESSIAH', 'platform': ['windows']} self.sdkInfo['swarm'] = {'sdk': 'HL2SDK-SWARM', 'ext': '2.swarm', 'def': '7', @@ -33,10 +33,10 @@ class MMS: if AMBuild.target['platform'] != 'darwin': envvars['HL2SDK'] = 'hl2sdk' envvars['HL2SDKOB'] = 'hl2sdk-ob' - envvars['HL2SDKL4D'] = 'hl2sdk-l4d' - envvars['HL2SDKL4D2'] = 'hl2sdk-l4d2' envvars['HL2SDKOBVALVE'] = 'hl2sdk-ob-valve' + envvars['HL2SDKL4D'] = 'hl2sdk-l4d' + envvars['HL2SDKL4D2'] = 'hl2sdk-l4d2' #Dark Messiah is Windows-only if AMBuild.target['platform'] == 'windows': @@ -83,6 +83,7 @@ class MMS: self.compiler.AddToListVar('CFLAGS', '-mfpmath=sse') self.compiler.AddToListVar('CFLAGS', '-msse') self.compiler.AddToListVar('CFLAGS', '-m32') + self.compiler.AddToListVar('POSTLINKFLAGS', '-m32') self.compiler.AddToListVar('CFLAGS', '-static-libgcc') self.compiler.AddToListVar('CXXFLAGS', '-fno-exceptions') self.compiler.AddToListVar('CXXFLAGS', '-fno-rtti') @@ -218,7 +219,7 @@ class MMS: else: staticLibs = os.path.join(sdkPath, 'lib', 'linux') workFolder = os.path.join(AMBuild.outputFolder, job.workFolder) - if sdk == 'ep2v' or sdk == 'l4d2': + if sdk in ['ep2v', 'l4d', 'l4d2']: for i in ['tier1_i486.a', 'libvstdlib.so', 'libtier0.so']: link = os.path.join(workFolder, i) target = os.path.join(staticLibs, i) @@ -300,7 +301,7 @@ class MMS: if not noLink: if AMBuild.target['platform'] == 'linux': compiler['POSTLINKFLAGS'][0:0] = ['-lm'] - if sdk == 'ep2v' or sdk == 'l4d2': + if sdk in ['ep2v', 'l4d', 'l4d2']: compiler['POSTLINKFLAGS'][0:0] = ['libtier0.so'] compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.so'] else: diff --git a/core/AMBuilder b/core/AMBuilder index 471cecc..be83383 100644 --- a/core/AMBuilder +++ b/core/AMBuilder @@ -23,6 +23,10 @@ for i in MMS.sdkInfo: 'provider/provider_ep2.cpp', 'sourcehook/sourcehook.cpp', 'sourcehook/sourcehook_hookmangen.cpp', + 'sourcehook/sourcehook_impl_chookidman.cpp', + 'sourcehook/sourcehook_impl_chookmaninfo.cpp', + 'sourcehook/sourcehook_impl_cproto.cpp', + 'sourcehook/sourcehook_impl_cvfnptr.cpp', 'gamedll_bridge.cpp', 'vsp_bridge.cpp' ] diff --git a/core/sourcehook/generate/sh_memfuncinfo.h b/core/sourcehook/generate/sh_memfuncinfo.h index 8614d93..13c40a6 100644 --- a/core/sourcehook/generate/sh_memfuncinfo.h +++ b/core/sourcehook/generate/sh_memfuncinfo.h @@ -1,5 +1,5 @@ /* ======== SourceHook ======== -* Copyright (C) 2004-2008 Metamod:Source Development Team +* Copyright (C) 2004-2010 Metamod:Source Development Team * No warranties of any kind * * License: zlib/libpng diff --git a/core/sourcehook/generate/sh_memfuncinfo.hxx b/core/sourcehook/generate/sh_memfuncinfo.hxx index 19e6e1e..086a25d 100644 --- a/core/sourcehook/generate/sh_memfuncinfo.hxx +++ b/core/sourcehook/generate/sh_memfuncinfo.hxx @@ -1,5 +1,5 @@ /* ======== SourceHook ======== -* Copyright (C) 2004-2008 Metamod:Source Development Team +* Copyright (C) 2004-2010 Metamod:Source Development Team * No warranties of any kind * * License: zlib/libpng diff --git a/core/sourcehook/generate/shworker.exe b/core/sourcehook/generate/shworker.exe index a251da1..4362910 100644 Binary files a/core/sourcehook/generate/shworker.exe and b/core/sourcehook/generate/shworker.exe differ diff --git a/core/sourcehook/generate/shworker/msvc9/shworker.sln b/core/sourcehook/generate/shworker/msvc9/shworker.sln new file mode 100644 index 0000000..87f5ddc --- /dev/null +++ b/core/sourcehook/generate/shworker/msvc9/shworker.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shworker", "shworker.vcproj", "{7CD76E64-A9DF-47DB-8A68-36297C67E557}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7CD76E64-A9DF-47DB-8A68-36297C67E557}.Debug|Win32.ActiveCfg = Debug|Win32 + {7CD76E64-A9DF-47DB-8A68-36297C67E557}.Debug|Win32.Build.0 = Debug|Win32 + {7CD76E64-A9DF-47DB-8A68-36297C67E557}.Release|Win32.ActiveCfg = Release|Win32 + {7CD76E64-A9DF-47DB-8A68-36297C67E557}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/core/sourcehook/generate/shworker/msvc9/shworker.vcproj b/core/sourcehook/generate/shworker/msvc9/shworker.vcproj new file mode 100644 index 0000000..b174ea4 --- /dev/null +++ b/core/sourcehook/generate/shworker/msvc9/shworker.vcproj @@ -0,0 +1,207 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="9,00" + Name="shworker" + ProjectGUID="{7CD76E64-A9DF-47DB-8A68-36297C67E557}" + Keyword="Win32Proj" + TargetFrameworkVersion="131072" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="Debug" + IntermediateDirectory="Debug" + ConfigurationType="1" + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + CharacterSet="2" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;stricmp=_stricmp" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="true" + DebugInformationFormat="4" + DisableSpecificWarnings="4996" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + OutputFile="$(OutDir)/shworker.exe" + LinkIncremental="2" + GenerateDebugInformation="true" + ProgramDatabaseFile="$(OutDir)/shworker.pdb" + SubSystem="1" + RandomizedBaseAddress="1" + DataExecutionPrevention="0" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="Release" + IntermediateDirectory="Release" + ConfigurationType="1" + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + CharacterSet="2" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + InlineFunctionExpansion="1" + OmitFramePointers="true" + PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;stricmp=_stricmp" + StringPooling="true" + RuntimeLibrary="0" + EnableFunctionLevelLinking="true" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="true" + DebugInformationFormat="3" + DisableSpecificWarnings="4996" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + OutputFile="$(OutDir)/shworker.exe" + LinkIncremental="1" + GenerateDebugInformation="true" + SubSystem="1" + OptimizeReferences="2" + EnableCOMDATFolding="2" + RandomizedBaseAddress="1" + DataExecutionPrevention="0" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm" + > + <File + RelativePath="..\fd_hopter.cpp" + > + </File> + <File + RelativePath="..\shworker.cpp" + > + </File> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl;inc" + > + </Filter> + <Filter + Name="Resource Files" + Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" + > + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/core/sourcehook/generate/shworker/shworker.cpp b/core/sourcehook/generate/shworker/shworker.cpp index be328ef..5e0047c 100644 --- a/core/sourcehook/generate/shworker/shworker.cpp +++ b/core/sourcehook/generate/shworker/shworker.cpp @@ -743,7 +743,7 @@ int main(int argc, const char **argv) const char *action = argv[1]; - if (strcasecmp(action, "hopter") == 0) + if (stricmp(action, "hopter") == 0) { const char *filenamein = argv[2]; const char *filenameout = argv[3]; @@ -751,7 +751,7 @@ int main(int argc, const char **argv) return action_hopter(argsnum, filenamein, filenameout); } - else if (strcasecmp(action, "iter") == 0) + else if (stricmp(action, "iter") == 0) { const char *filenamein = argv[2]; const char *filenameout = argv[3]; diff --git a/core/sourcehook/generate/sourcehook.h b/core/sourcehook/generate/sourcehook.h index 275cdf4..ba28315 100644 --- a/core/sourcehook/generate/sourcehook.h +++ b/core/sourcehook/generate/sourcehook.h @@ -1,5 +1,5 @@ /* ======== SourceHook ======== -* Copyright (C) 2004-2008 Metamod:Source Development Team +* Copyright (C) 2004-2010 Metamod:Source Development Team * No warranties of any kind * * License: zlib/libpng @@ -307,6 +307,20 @@ namespace SourceHook }; }; + template <class T> struct ReferenceUtil + { + typedef T plain_type; + typedef T* pointer_type; + typedef T& reference_type; + }; + + template <class T> struct ReferenceUtil<T&> + { + typedef T plain_type; + typedef T* pointer_type; + typedef T& reference_type; + }; + struct IHookContext { virtual ISHDelegate *GetNext() = 0; @@ -480,7 +494,7 @@ namespace SourceHook * @return Override Return Pointer the hookfunc should use (may differ from overrideRetPtr * when the hook func is being called as part of a recall */ - virtual IHookContext *SetupHookLoop(IHookManagerInfo *hi, void *vfnptr, void *thisptr, void **origentry, + virtual IHookContext *SetupHookLoop(IHookManagerInfo *hi, void *vfnptr, void *thisptr, void **origCallAddr, META_RES *statusPtr, META_RES *prevResPtr, META_RES *curResPtr, const void *origRetPtr, void *overrideRetPtr) = 0; @@ -579,10 +593,14 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) // only call these from the hook handlers directly! +#define MAKE_NOREF_VALUE(rettype) \ + *reinterpret_cast< ::SourceHook::ReferenceUtil<rettype>::pointer_type >(0) + // If a hook on a function which returns a reference does not want to specify a return value, // it can use this macro. // ONLY USE THIS WITH MRES_IGNORED AND MRES_HANDLED !!! -#define RETURN_META_NOREF(result, rettype) do { SET_META_RESULT(result); return reinterpret_cast<rettype>(*SH_GLOB_SHPTR); } while(0) +#define RETURN_META_NOREF(result, rettype) \ + RETURN_META_VALUE(result, MAKE_NOREF_VALUE(rettype)) // Why take a memfuncptr instead of iface and func when we have to deduce the iface anyway now? // Well, without it, there'd be no way to specify which overloaded version we want in _VALUE @@ -1163,7 +1181,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN0(hookname, rettype) \ @@ -1196,7 +1214,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN0_vafmt(hookname, rettype) \ @@ -1368,7 +1386,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN1(hookname, rettype, param1) \ @@ -1401,7 +1419,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN1_vafmt(hookname, rettype, param1) \ @@ -1573,7 +1591,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN2(hookname, rettype, param1, param2) \ @@ -1606,7 +1624,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN2_vafmt(hookname, rettype, param1, param2) \ @@ -1778,7 +1796,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN3(hookname, rettype, param1, param2, param3) \ @@ -1811,7 +1829,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN3_vafmt(hookname, rettype, param1, param2, param3) \ @@ -1983,7 +2001,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN4(hookname, rettype, param1, param2, param3, param4) \ @@ -2016,7 +2034,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN4_vafmt(hookname, rettype, param1, param2, param3, param4) \ @@ -2188,7 +2206,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN5(hookname, rettype, param1, param2, param3, param4, param5) \ @@ -2221,7 +2239,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN5_vafmt(hookname, rettype, param1, param2, param3, param4, param5) \ @@ -2393,7 +2411,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN6(hookname, rettype, param1, param2, param3, param4, param5, param6) \ @@ -2426,7 +2444,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN6_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6) \ @@ -2598,7 +2616,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN7(hookname, rettype, param1, param2, param3, param4, param5, param6, param7) \ @@ -2631,7 +2649,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN7_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7) \ @@ -2803,7 +2821,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN8(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ @@ -2836,7 +2854,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN8_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ @@ -3008,7 +3026,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN9(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ @@ -3041,7 +3059,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN9_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ @@ -3213,7 +3231,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN10(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ @@ -3246,7 +3264,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN10_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ @@ -3418,7 +3436,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN11(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ @@ -3451,7 +3469,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN11_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ @@ -3623,7 +3641,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN12(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ @@ -3656,7 +3674,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN12_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ @@ -3828,7 +3846,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN13(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ @@ -3861,7 +3879,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN13_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ @@ -4033,7 +4051,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN14(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ @@ -4066,7 +4084,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN14_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ @@ -4238,7 +4256,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN15(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ @@ -4271,7 +4289,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN15_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ @@ -4443,7 +4461,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN16(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ @@ -4476,7 +4494,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN16_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ @@ -6737,12 +6755,6 @@ SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Para namespace SourceHook { - template <class RetType> - void SetOverrideResult(ISourceHook *shptr, const RetType res) - { - *reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res; - } - // SetOverrideResult used to be implemented like this: // SetOverrideResult(shptr, memfuncptr, return); // normally the compiler can deduce the return type from memfuncptr, but (at least msvc8) failed when it was a reference @@ -6767,6 +6779,14 @@ namespace SourceHook } }; + // For manual hooks: + // The rettype is passed in manually + template <class RetType> + OverrideFunctor<RetType> SetOverrideResult() + { + return OverrideFunctor<RetType>(); + } + template <class Iface, class RetType> OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)()) { diff --git a/core/sourcehook/generate/sourcehook.hxx b/core/sourcehook/generate/sourcehook.hxx index 60bf039..921942c 100755 --- a/core/sourcehook/generate/sourcehook.hxx +++ b/core/sourcehook/generate/sourcehook.hxx @@ -1,5 +1,5 @@ /* ======== SourceHook ======== -* Copyright (C) 2004-2008 Metamod:Source Development Team +* Copyright (C) 2004-2010 Metamod:Source Development Team * No warranties of any kind * * License: zlib/libpng @@ -307,6 +307,20 @@ namespace SourceHook }; }; + template <class T> struct ReferenceUtil + { + typedef T plain_type; + typedef T* pointer_type; + typedef T& reference_type; + }; + + template <class T> struct ReferenceUtil<T&> + { + typedef T plain_type; + typedef T* pointer_type; + typedef T& reference_type; + }; + struct IHookContext { virtual ISHDelegate *GetNext() = 0; @@ -480,7 +494,7 @@ namespace SourceHook * @return Override Return Pointer the hookfunc should use (may differ from overrideRetPtr * when the hook func is being called as part of a recall */ - virtual IHookContext *SetupHookLoop(IHookManagerInfo *hi, void *vfnptr, void *thisptr, void **origentry, + virtual IHookContext *SetupHookLoop(IHookManagerInfo *hi, void *vfnptr, void *thisptr, void **origCallAddr, META_RES *statusPtr, META_RES *prevResPtr, META_RES *curResPtr, const void *origRetPtr, void *overrideRetPtr) = 0; @@ -579,10 +593,14 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) // only call these from the hook handlers directly! +#define MAKE_NOREF_VALUE(rettype) \ + *reinterpret_cast< ::SourceHook::ReferenceUtil<rettype>::pointer_type >(0) + // If a hook on a function which returns a reference does not want to specify a return value, // it can use this macro. // ONLY USE THIS WITH MRES_IGNORED AND MRES_HANDLED !!! -#define RETURN_META_NOREF(result, rettype) do { SET_META_RESULT(result); return reinterpret_cast<rettype>(*SH_GLOB_SHPTR); } while(0) +#define RETURN_META_NOREF(result, rettype) \ + RETURN_META_VALUE(result, MAKE_NOREF_VALUE(rettype)) // Why take a memfuncptr instead of iface and func when we have to deduce the iface anyway now? // Well, without it, there'd be no way to specify which overloaded version we want in _VALUE @@ -1163,7 +1181,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN$1(hookname, rettype@[$2,1,$1:, param$2@]) \ @@ -1196,7 +1214,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN$1_vafmt(hookname, rettype@[$2,1,$1:, param$2@]) \ @@ -1415,12 +1433,6 @@ SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(@[$2,1,$1|, :Param$2@]@[$1!=0:, @].. namespace SourceHook { - template <class RetType> - void SetOverrideResult(ISourceHook *shptr, const RetType res) - { - *reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res; - } - // SetOverrideResult used to be implemented like this: // SetOverrideResult(shptr, memfuncptr, return); // normally the compiler can deduce the return type from memfuncptr, but (at least msvc8) failed when it was a reference @@ -1444,6 +1456,14 @@ namespace SourceHook *reinterpret_cast<typename ReferenceCarrier<T&>::type *>(shptr->GetOverrideRetPtr()) = res; } }; + + // For manual hooks: + // The rettype is passed in manually + template <class RetType> + OverrideFunctor<RetType> SetOverrideResult() + { + return OverrideFunctor<RetType>(); + } @[$1,0,$a: template <class Iface, class RetType@[$2,1,$1:, class Param$2@]> OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)(@[$2,1,$1|, :Param$2@])) diff --git a/core/sourcehook/sh_list.h b/core/sourcehook/sh_list.h index 1e56b9d..21d57c0 100644 --- a/core/sourcehook/sh_list.h +++ b/core/sourcehook/sh_list.h @@ -1,5 +1,5 @@ /* ======== SourceMM ======== -* Copyright (C) 2004-2008 Metamod:Source Development Team +* Copyright (C) 2004-2010 Metamod:Source Development Team * No warranties of any kind * * License: zlib/libpng diff --git a/core/sourcehook/sh_memfuncinfo.h b/core/sourcehook/sh_memfuncinfo.h index 8614d93..13c40a6 100644 --- a/core/sourcehook/sh_memfuncinfo.h +++ b/core/sourcehook/sh_memfuncinfo.h @@ -1,5 +1,5 @@ /* ======== SourceHook ======== -* Copyright (C) 2004-2008 Metamod:Source Development Team +* Copyright (C) 2004-2010 Metamod:Source Development Team * No warranties of any kind * * License: zlib/libpng diff --git a/core/sourcehook/sh_memory.h b/core/sourcehook/sh_memory.h index f69d273..f3e03d0 100644 --- a/core/sourcehook/sh_memory.h +++ b/core/sourcehook/sh_memory.h @@ -1,5 +1,5 @@ /* ======== SourceHook ======== -* Copyright (C) 2004-2008 Metamod:Source Development Team +* Copyright (C) 2004-2010 Metamod:Source Development Team * No warranties of any kind * * License: zlib/libpng diff --git a/core/sourcehook/sh_pagealloc.h b/core/sourcehook/sh_pagealloc.h index 15400fc..0becac7 100644 --- a/core/sourcehook/sh_pagealloc.h +++ b/core/sourcehook/sh_pagealloc.h @@ -1,6 +1,9 @@ #ifndef __SH_PAGEALLOC_H__ #define __SH_PAGEALLOC_H__ +#include "sh_list.h" +#include "sh_memory.h" + # if SH_XP == SH_XP_WINAPI # include <windows.h> # elif SH_XP == SH_XP_POSIX @@ -53,6 +56,7 @@ namespace SourceHook bool isolated; // may contain only one AU size_t minAlignment; AUList allocUnits; + bool isRE; // true: RE, otherwise: RW void CheckGap(size_t gap_begin, size_t gap_end, size_t reqsize, size_t &smallestgap_pos, size_t &smallestgap_size, size_t &outAlignBytes) @@ -122,9 +126,11 @@ namespace SourceHook void *alignedAUBegin = reinterpret_cast<void*>( AUBegin + ((minAlignment - AUBegin % minAlignment) % minAlignment) ); - + if (addr == alignedAUBegin) { + DebugCleanMemory(reinterpret_cast<unsigned char*>(startPtr) + iter->begin_offset, + iter->size); allocUnits.erase(iter); return true; } @@ -133,6 +139,26 @@ namespace SourceHook return false; } + void DebugCleanMemory(unsigned char* start, size_t size) + { + bool wasRE = isRE; + if (isRE) + { + SetRW(); + } + + unsigned char* end = start + size; + for (unsigned char* p = start; p != end; ++p) + { + *p = 0xCC; + } + + if (wasRE) + { + SetRE(); + } + } + bool Contains(void *addr) { return addr >= startPtr && addr < reinterpret_cast<void*>(reinterpret_cast<char*>(startPtr) + size); @@ -146,6 +172,18 @@ namespace SourceHook VirtualFree(startPtr, 0, MEM_RELEASE); #endif } + + void SetRE() + { + SetMemAccess(startPtr, size, SH_MEM_READ | SH_MEM_EXEC); + isRE = true; + } + + void SetRW() + { + SetMemAccess(startPtr, size, SH_MEM_READ | SH_MEM_WRITE); + isRE = false; + } }; typedef List<AllocatedRegion> ARList; @@ -178,6 +216,7 @@ namespace SourceHook if (newRegion.startPtr) { + newRegion.SetRW(); m_Regions.push_back(newRegion); return true; } @@ -210,7 +249,7 @@ namespace SourceHook } public: - CPageAlloc(size_t minAlignment = 1 /* power of 2 */ ) : m_MinAlignment(minAlignment) + CPageAlloc(size_t minAlignment = 4 /* power of 2 */ ) : m_MinAlignment(minAlignment) { #if SH_XP == SH_XP_POSIX m_PageSize = sysconf(_SC_PAGESIZE); @@ -262,7 +301,7 @@ namespace SourceHook { if (iter->Contains(ptr)) { - SetMemAccess(iter->startPtr, iter->size, SH_MEM_READ | SH_MEM_EXEC); + iter->SetRE(); break; } } @@ -274,7 +313,7 @@ namespace SourceHook { if (iter->Contains(ptr)) { - SetMemAccess(iter->startPtr, iter->size, SH_MEM_READ | SH_MEM_WRITE); + iter->SetRW(); break; } } diff --git a/core/sourcehook/sh_stack.h b/core/sourcehook/sh_stack.h index e6269e6..5322db2 100644 --- a/core/sourcehook/sh_stack.h +++ b/core/sourcehook/sh_stack.h @@ -1,5 +1,5 @@ /* ======== SourceMM ======== -* Copyright (C) 2004-2008 Metamod:Source Development Team +* Copyright (C) 2004-2010 Metamod:Source Development Team * No warranties of any kind * * License: zlib/libpng diff --git a/core/sourcehook/sh_string.h b/core/sourcehook/sh_string.h index 79f96b8..6d6a8a5 100755 --- a/core/sourcehook/sh_string.h +++ b/core/sourcehook/sh_string.h @@ -1,5 +1,5 @@ /* ======== SourceMM ======== -* Copyright (C) 2004-2008 Metamod:Source Development Team +* Copyright (C) 2004-2010 Metamod:Source Development Team * No warranties of any kind * * License: zlib/libpng diff --git a/core/sourcehook/sh_tinyhash.h b/core/sourcehook/sh_tinyhash.h index 67f3adf..60b919c 100644 --- a/core/sourcehook/sh_tinyhash.h +++ b/core/sourcehook/sh_tinyhash.h @@ -1,5 +1,5 @@ /* ======== SourceMM ======== -* Copyright (C) 2004-2008 Metamod:Source Development Team +* Copyright (C) 2004-2010 Metamod:Source Development Team * No warranties of any kind * * License: zlib/libpng diff --git a/core/sourcehook/sourcehook.cpp b/core/sourcehook/sourcehook.cpp index 8bb9035..58f8086 100644 --- a/core/sourcehook/sourcehook.cpp +++ b/core/sourcehook/sourcehook.cpp @@ -1,5 +1,5 @@ /* ======== SourceHook ======== -* Copyright (C) 2004-2008 Metamod:Source Development Team +* Copyright (C) 2004-2010 Metamod:Source Development Team * No warranties of any kind * * License: zlib/libpng @@ -41,373 +41,33 @@ namespace SourceHook namespace Impl { - ////////////////////////////////////////////////////////////////////////// - // CProto - ////////////////////////////////////////////////////////////////////////// - void CProto::Fill(const ProtoInfo *pProto) - { - if (pProto == NULL) - m_Version = -1; - - m_ParamsPassInfo.clear(); - - if (pProto->paramsPassInfo[0].size == 0) - { - // Version 1 - m_Version = 0; - m_Convention = pProto->convention; - m_NumOfParams = pProto->numOfParams; - - m_RetPassInfo.size = pProto->retPassInfo.size; - m_RetPassInfo.type = pProto->retPassInfo.type; - m_RetPassInfo.flags = GetRealFlags(pProto->retPassInfo); - - m_RetPassInfo.pNormalCtor = NULL; - m_RetPassInfo.pCopyCtor = NULL; - m_RetPassInfo.pDtor = NULL; - m_RetPassInfo.pAssignOperator = NULL; - - - m_ParamsPassInfo.resize(pProto->numOfParams); - - for (int i = 1; i <= pProto->numOfParams; ++i) - { - m_ParamsPassInfo[i-1].size = pProto->paramsPassInfo[i].size; - m_ParamsPassInfo[i-1].type = pProto->paramsPassInfo[i].type; - m_ParamsPassInfo[i-1].flags = GetRealFlags(pProto->paramsPassInfo[i]); - - m_ParamsPassInfo[i-1].pNormalCtor = NULL; - m_ParamsPassInfo[i-1].pCopyCtor = NULL; - m_ParamsPassInfo[i-1].pDtor = NULL; - m_ParamsPassInfo[i-1].pAssignOperator = NULL; - } - } - else if (pProto->paramsPassInfo[0].size == 1) - { - // Version 2 - m_Version = 1; - m_Convention = pProto->convention; - m_NumOfParams = pProto->numOfParams; - - m_RetPassInfo.size = pProto->retPassInfo.size; - m_RetPassInfo.type = pProto->retPassInfo.type; - m_RetPassInfo.flags = pProto->retPassInfo.flags; - - m_RetPassInfo.pNormalCtor = pProto->retPassInfo2.pNormalCtor; - m_RetPassInfo.pCopyCtor = pProto->retPassInfo2.pCopyCtor; - m_RetPassInfo.pDtor = pProto->retPassInfo2.pDtor; - m_RetPassInfo.pAssignOperator = pProto->retPassInfo2.pAssignOperator; - - m_ParamsPassInfo.resize(pProto->numOfParams); - - for (int i = 1; i <= pProto->numOfParams; ++i) - { - m_ParamsPassInfo[i-1].size = pProto->paramsPassInfo[i].size; - m_ParamsPassInfo[i-1].type = pProto->paramsPassInfo[i].type; - m_ParamsPassInfo[i-1].flags = pProto->paramsPassInfo[i].flags; - - m_ParamsPassInfo[i-1].pNormalCtor = pProto->paramsPassInfo2[i].pNormalCtor; - m_ParamsPassInfo[i-1].pCopyCtor = pProto->paramsPassInfo2[i].pCopyCtor; - m_ParamsPassInfo[i-1].pDtor = pProto->paramsPassInfo2[i].pDtor; - m_ParamsPassInfo[i-1].pAssignOperator = pProto->paramsPassInfo2[i].pAssignOperator; - } - } - else - { - // Unknown - m_Version = -1; - } - } - - // Basic compat test - // Other than this, we assume that the plugins know what they're doing - bool CProto::operator == (const CProto &other) const - { - if (m_Version < 0 || other.GetVersion() < 0) - return false; - - if (m_NumOfParams != other.GetNumOfParams()) - return false; - - if (m_Convention != ProtoInfo::CallConv_Unknown && other.GetConvention() != ProtoInfo::CallConv_Unknown && - m_Convention != other.GetConvention()) - return false; - - if (GetRealSize(GetRet()) != GetRealSize(other.GetRet())) - return false; - - for (int i = 0; i < m_NumOfParams; ++i) - { - if (GetRealSize(GetParam(i)) != GetRealSize(other.GetParam(i))) - return false; - if (GetParam(i).type != PassInfo::PassType_Unknown && other.GetParam(i).type != PassInfo::PassType_Unknown) - { - if (GetParam(i).type != other.GetParam(i).type) - return false; - if (GetParam(i).flags != other.GetParam(i).flags) - return false; - } - } - - return true; - } - - bool CProto::ExactlyEqual(const CProto &other) const - { - if (m_Version != other.m_Version || - m_NumOfParams != other.m_NumOfParams || - m_Convention != other.m_Convention || - GetRet() != other.GetRet()) - { - return false; - } - - for (int i = 0; i < m_NumOfParams; ++i) - { - if(GetParam(i) != other.GetParam(i)) - return false; - } - - return true; - } - - ////////////////////////////////////////////////////////////////////////// - // CHookManager - ////////////////////////////////////////////////////////////////////////// - void CHookManager::SetInfo(int hookman_version, int vtbloffs, int vtblidx, - ProtoInfo *proto, void *hookfunc_vfnptr) - { - m_Version = hookman_version; - m_VtblOffs = vtbloffs; - m_VtblIdx = vtblidx; - m_Proto = proto; - m_HookfuncVfnptr = hookfunc_vfnptr; - } - ////////////////////////////////////////////////////////////////////////// // CVfnPtrList ////////////////////////////////////////////////////////////////////////// - CVfnPtr &CVfnPtrList::GetVfnPtr(void *vfnptr) + CVfnPtr *CVfnPtrList::GetVfnPtr(void *vfnptr) { iterator iter = find(vfnptr); if (iter == end()) { + // No vfnptr info object found + // --> create a new one CVfnPtr newVfnPtr(vfnptr); - push_back(newVfnPtr); - - return back(); - } - else - { - return *iter; - } - } - ////////////////////////////////////////////////////////////////////////// - // CVfnPtr - ////////////////////////////////////////////////////////////////////////// - - void CVfnPtr::AddHookMan(CHookManager *pHookMan) - { - List<CHookManager*>::iterator iter; - - // Don't accept invalid hook managers - if (!*pHookMan) - return; - - // Check whether this hook manager already exists; if yes, ignore. - iter = m_HookMans.find(pHookMan); - if (iter != m_HookMans.end()) - return; - - // It doesn't -> add it. Add it to the end of its version group. - for (iter = m_HookMans.begin(); iter != m_HookMans.end(); ++iter) - { - if ((*iter)->GetVersion() < pHookMan->GetVersion()) - break; - } - - bool isBeginning = iter == m_HookMans.begin(); - - m_HookMans.insert(iter, pHookMan); - - if (isBeginning) - { - pHookMan->IncrRef(this); - if (m_HookMans.size() > 1) + if (newVfnPtr.Init()) { - // If another hookman was used until now but this one is better - // (which it is because it's the first -> it has a higher version) - // -> switch! + push_back(newVfnPtr); - List<CHookManager*>::iterator second = m_HookMans.begin(); - ++second; - - (*second)->DecrRef(this); - } - - // Make sure that this vfnptr points at it - Patch(pHookMan->GetHookFunc()); - } - } - - bool CVfnPtr::HookManRemoved(CHookManager *pHookMan) - { - // Don't accept invalid hook managers - if (!*pHookMan) - return true; - - List<CHookManager*>::iterator iter = m_HookMans.find(pHookMan); - if (iter == m_HookMans.end()) - return true; // Didn't exist here anyway - - if (iter == m_HookMans.begin()) - { - // It is the first one! - pHookMan->DecrRef(this); - m_HookMans.erase(iter); - - if (m_HookMans.empty()) - return false; // No more hookmans -> let SH delete us - - // Activate second -> now first hookman - m_HookMans.front()->IncrRef(this); - Patch(m_HookMans.front()->GetHookFunc()); - } - else - { - m_HookMans.erase(iter); - } - return true; - } - - bool CVfnPtr::Patch(void *newValue) - { - if (!SetMemAccess(m_Ptr, sizeof(void*), SH_MEM_READ | SH_MEM_WRITE)) - { - return false; - } - - *reinterpret_cast<void**>(m_Ptr) = newValue; - - return true; - } - - CIface &CVfnPtr::GetIface(void *iface) - { - List<CIface>::iterator iter = m_IfaceList.find(iface); - if (iter == m_IfaceList.end()) - { - CIface newIface(iface); - if (iface == NULL) - { - m_IfaceList.push_front(newIface); - return m_IfaceList.front(); + return &(back()); } else { - m_IfaceList.push_back(newIface); - return m_IfaceList.back(); + // Initialization failed. + return NULL; } } else { - return *iter; - } - } - - ////////////////////////////////////////////////////////////////////////// - // CHookIdManager - ////////////////////////////////////////////////////////////////////////// - CHookIDManager::CHookIDManager() - { - } - - int CHookIDManager::New(const CProto &proto, int vtbl_offs, int vtbl_idx, void *vfnptr, - void *adjustediface, Plugin plug, int thisptr_offs, ISHDelegate *handler, bool post) - { - Entry tmp(proto, vtbl_offs, vtbl_idx, vfnptr, adjustediface, plug, thisptr_offs, handler, post); - - size_t cursize = m_Entries.size(); - for (size_t i = 0; i < cursize; ++i) - { - if (m_Entries[i].isfree) - { - m_Entries[i] = tmp; - return static_cast<int>(i) + 1; - } - } - - m_Entries.push_back(tmp); - return static_cast<int>(m_Entries.size()); // return size() because hookid = id+1 anyway - } - - bool CHookIDManager::Remove(int hookid) - { - int realid = hookid - 1; - if (realid < 0 || realid >= static_cast<int>(m_Entries.size()) || m_Entries[realid].isfree) - return false; - - m_Entries[realid].isfree = true; - - // :TODO: remove free ids from back sometimes ?? - - return true; - } - - const CHookIDManager::Entry * CHookIDManager::QueryHook(int hookid) - { - int realid = hookid - 1; - if (realid < 0 || realid >= static_cast<int>(m_Entries.size()) || m_Entries[realid].isfree) - return NULL; - - return &m_Entries[realid]; - } - - void CHookIDManager::FindAllHooks(CVector<int> &output, const CProto &proto, int vtbl_offs, - int vtbl_idx, void *adjustediface, Plugin plug, int thisptr_offs, ISHDelegate *handler, bool post) - { - // oh my god, a lot of parameters... - size_t cursize = m_Entries.size(); - for (size_t i = 0; i < cursize; ++i) - { - if (!m_Entries[i].isfree && m_Entries[i].proto == proto && m_Entries[i].vtbl_offs == vtbl_offs && - m_Entries[i].vtbl_idx == vtbl_idx && m_Entries[i].adjustediface == adjustediface && m_Entries[i].plug == plug && - m_Entries[i].thisptr_offs == thisptr_offs && m_Entries[i].handler->IsEqual(handler) && m_Entries[i].post == post) - { - output.push_back(static_cast<int>(i) + 1); - } - } - } - - void CHookIDManager::FindAllHooks(CVector<int> &output) - { - size_t cursize = m_Entries.size(); - for (size_t i = 0; i < cursize; ++i) - { - if (!m_Entries[i].isfree) - output.push_back(static_cast<int>(i) + 1); - } - } - - void CHookIDManager::FindAllHooks(CVector<int> &output, Plugin plug) - { - size_t cursize = m_Entries.size(); - for (size_t i = 0; i < cursize; ++i) - { - if (!m_Entries[i].isfree && m_Entries[i].plug == plug) - output.push_back(static_cast<int>(i) + 1); - } - } - - - void CHookIDManager::RemoveAll(void *vfnptr) - { - size_t cursize = m_Entries.size(); - for (size_t i = 0; i < cursize; ++i) - { - if (!m_Entries[i].isfree && m_Entries[i].vfnptr == vfnptr) - m_Entries[i].isfree = true; + return &(*iter); } } @@ -480,9 +140,18 @@ namespace SourceHook break; } - CVfnPtr &vfnPtr = m_VfnPtrs.GetVfnPtr(cur_vfnptr); - vfnPtr.AddHookMan(m_HookManList.GetHookMan(hookManager)); - CIface &ifaceinst = vfnPtr.GetIface(adjustediface); + CVfnPtr *vfnPtr = m_VfnPtrs.GetVfnPtr(cur_vfnptr); + if (!vfnPtr) + { + // Could not create the vfnptr info object. + // This could be because a thunk generation on GCC + // has failed. See sourcehook_impl_cvfnptr.cpp + // for details. + return false; + } + + vfnPtr->AddHookMan(m_HookManList.GetHookMan(hookManager)); + CIface &ifaceinst = vfnPtr->GetIface(adjustediface); // Add the hook CHook hook(plug, thisptr_offs, handler, @@ -588,9 +257,7 @@ namespace SourceHook ctx_iter->VfnPtrRemoved(&(*vfnptr_iter)); } - vfnptr_iter->Revert(); - - m_VfnPtrs.erase(vfnptr_iter); + RevertAndRemoveVfnPtr(vfnptr_iter); } } @@ -598,6 +265,52 @@ namespace SourceHook return true; } + List<CVfnPtr>::iterator CSourceHookImpl::RevertAndRemoveVfnPtr(List<CVfnPtr>::iterator vfnptr_iter) + { + ICleanupTask *cleanupTask = vfnptr_iter->GetCleanupTask(); + + // Some vfnptrs require cleanup. + // Concrete case: on GCC, when the original vtable entry is not even + // we generate an even-aligned thunk to call the original function. + // If the vfnptr is being removed from a pre hook on the vfnptr + // we have to delay the cleanup of this thunk until the hook loop is done + // (because the orig function call mechanism is going to use the thunk). + + if (cleanupTask != NULL) + { + // If this vfnptr is in use in one of the hook loops running at the moment + // Schedule it for removal on the DEEPEST hook loop. + + size_t numOfContexts = m_ContextStack.size(); + // m_ContextStack.at(0) is the deepest hook context + // m_ContextStack.at(size-1) = m_ContextStack.front is the uppermost + + bool cleanupImmedieately = true; + + CVfnPtr *vfnPtrObjAddr = &(*vfnptr_iter); + for (size_t i = 0; i < numOfContexts; ++i) + { + CHookContext &context = m_ContextStack.at(i); + if (context.pVfnPtr == vfnPtrObjAddr) + { + // Found a hook context using this vfnptr at the moment. + context.m_CleanupTask = cleanupTask; + cleanupImmedieately = false; // Delay the cleanup + break; + } + } + + if (cleanupImmedieately) + { + cleanupTask->CleanupAndDeleteThis(); + } + } + + // Do the work + vfnptr_iter->Revert(); + return m_VfnPtrs.erase(vfnptr_iter); + } + void CSourceHookImpl::SetRes(META_RES res) { *m_ContextStack.front().pCurRes = res; @@ -675,10 +388,9 @@ namespace SourceHook // This vfnptr has no more hook managers // and asks to be removed. - vfnptr_iter->Revert(); - m_HookIDMan.RemoveAll(vfnptr_iter->GetPtr()); - vfnptr_iter = m_VfnPtrs.erase(vfnptr_iter); + + vfnptr_iter = RevertAndRemoveVfnPtr(vfnptr_iter); } else { @@ -710,7 +422,12 @@ namespace SourceHook void CSourceHookImpl::ResetIgnoreHooks(void *vfnptr) { if (!m_ContextStack.empty() && m_ContextStack.front().m_State == CHookContext::State_Ignore) - m_ContextStack.pop(); + { + // Actually use EndContext + // instead of m_ContextStack.pop directly + // because it runs the cleanup task if neccesary + EndContext(&(m_ContextStack.front())); + } } void *CSourceHookImpl::GetOrigVfnPtrEntry(void *vfnptr) @@ -753,7 +470,7 @@ namespace SourceHook curCtx.m_State = CHookContext::State_Dead; } - IHookContext *CSourceHookImpl::SetupHookLoop(IHookManagerInfo *hi, void *vfnptr, void *thisptr, void **origentry, META_RES *statusPtr, + IHookContext *CSourceHookImpl::SetupHookLoop(IHookManagerInfo *hi, void *vfnptr, void *thisptr, void **origCallAddr, META_RES *statusPtr, META_RES *prevResPtr, META_RES *curResPtr, const void *origRetPtr, void *overrideRetPtr) { CHookContext *pCtx = NULL; @@ -781,7 +498,8 @@ namespace SourceHook } else { - *origentry = (*vfnptr_iter)->GetOrigEntry(); + *origCallAddr = (*vfnptr_iter)->GetOrigCallAddr(); + oldctx->pVfnPtr = *vfnptr_iter; } oldctx->pOrigRet = origRetPtr; @@ -839,7 +557,7 @@ namespace SourceHook else { pCtx->pVfnPtr = *vfnptr_iter; - *origentry = pCtx->pVfnPtr->GetOrigEntry(); + *origCallAddr = pCtx->pVfnPtr->GetOrigCallAddr(); pCtx->pIface = pCtx->pVfnPtr->FindIface(thisptr); } @@ -855,6 +573,9 @@ namespace SourceHook void CSourceHookImpl::EndContext(IHookContext *pCtx) { + // Do clean up task, if any is associated with this context + m_ContextStack.front().DoCleanupTaskAndDeleteIt(); + // Then remove it m_ContextStack.pop(); } @@ -1085,9 +806,22 @@ namespace SourceHook { if (pVfnPtr == vfnptr) { - pVfnPtr = NULL; + // Don't set pVfnPtr = NULL here! + // It may be used still. + // RevertAndRemoveVfnPtr uses it to find the hook context + // to which to attach the cleanup task of the vfnptr. + + //pVfnPtr = NULL; m_State = State_Dead; } } + + void CHookContext::DoCleanupTaskAndDeleteIt() + { + if (m_CleanupTask != NULL) + { + m_CleanupTask->CleanupAndDeleteThis(); + } + } } } diff --git a/core/sourcehook/sourcehook.h b/core/sourcehook/sourcehook.h index 275cdf4..ba28315 100644 --- a/core/sourcehook/sourcehook.h +++ b/core/sourcehook/sourcehook.h @@ -1,5 +1,5 @@ /* ======== SourceHook ======== -* Copyright (C) 2004-2008 Metamod:Source Development Team +* Copyright (C) 2004-2010 Metamod:Source Development Team * No warranties of any kind * * License: zlib/libpng @@ -307,6 +307,20 @@ namespace SourceHook }; }; + template <class T> struct ReferenceUtil + { + typedef T plain_type; + typedef T* pointer_type; + typedef T& reference_type; + }; + + template <class T> struct ReferenceUtil<T&> + { + typedef T plain_type; + typedef T* pointer_type; + typedef T& reference_type; + }; + struct IHookContext { virtual ISHDelegate *GetNext() = 0; @@ -480,7 +494,7 @@ namespace SourceHook * @return Override Return Pointer the hookfunc should use (may differ from overrideRetPtr * when the hook func is being called as part of a recall */ - virtual IHookContext *SetupHookLoop(IHookManagerInfo *hi, void *vfnptr, void *thisptr, void **origentry, + virtual IHookContext *SetupHookLoop(IHookManagerInfo *hi, void *vfnptr, void *thisptr, void **origCallAddr, META_RES *statusPtr, META_RES *prevResPtr, META_RES *curResPtr, const void *origRetPtr, void *overrideRetPtr) = 0; @@ -579,10 +593,14 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) // only call these from the hook handlers directly! +#define MAKE_NOREF_VALUE(rettype) \ + *reinterpret_cast< ::SourceHook::ReferenceUtil<rettype>::pointer_type >(0) + // If a hook on a function which returns a reference does not want to specify a return value, // it can use this macro. // ONLY USE THIS WITH MRES_IGNORED AND MRES_HANDLED !!! -#define RETURN_META_NOREF(result, rettype) do { SET_META_RESULT(result); return reinterpret_cast<rettype>(*SH_GLOB_SHPTR); } while(0) +#define RETURN_META_NOREF(result, rettype) \ + RETURN_META_VALUE(result, MAKE_NOREF_VALUE(rettype)) // Why take a memfuncptr instead of iface and func when we have to deduce the iface anyway now? // Well, without it, there'd be no way to specify which overloaded version we want in _VALUE @@ -1163,7 +1181,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN0(hookname, rettype) \ @@ -1196,7 +1214,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN0_vafmt(hookname, rettype) \ @@ -1368,7 +1386,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN1(hookname, rettype, param1) \ @@ -1401,7 +1419,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN1_vafmt(hookname, rettype, param1) \ @@ -1573,7 +1591,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN2(hookname, rettype, param1, param2) \ @@ -1606,7 +1624,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN2_vafmt(hookname, rettype, param1, param2) \ @@ -1778,7 +1796,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN3(hookname, rettype, param1, param2, param3) \ @@ -1811,7 +1829,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN3_vafmt(hookname, rettype, param1, param2, param3) \ @@ -1983,7 +2001,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN4(hookname, rettype, param1, param2, param3, param4) \ @@ -2016,7 +2034,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN4_vafmt(hookname, rettype, param1, param2, param3, param4) \ @@ -2188,7 +2206,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN5(hookname, rettype, param1, param2, param3, param4, param5) \ @@ -2221,7 +2239,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN5_vafmt(hookname, rettype, param1, param2, param3, param4, param5) \ @@ -2393,7 +2411,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN6(hookname, rettype, param1, param2, param3, param4, param5, param6) \ @@ -2426,7 +2444,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN6_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6) \ @@ -2598,7 +2616,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN7(hookname, rettype, param1, param2, param3, param4, param5, param6, param7) \ @@ -2631,7 +2649,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN7_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7) \ @@ -2803,7 +2821,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN8(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ @@ -2836,7 +2854,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN8_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ @@ -3008,7 +3026,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN9(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ @@ -3041,7 +3059,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN9_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ @@ -3213,7 +3231,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN10(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ @@ -3246,7 +3264,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN10_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ @@ -3418,7 +3436,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN11(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ @@ -3451,7 +3469,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN11_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ @@ -3623,7 +3641,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN12(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ @@ -3656,7 +3674,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN12_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ @@ -3828,7 +3846,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN13(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ @@ -3861,7 +3879,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN13_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ @@ -4033,7 +4051,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN14(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ @@ -4066,7 +4084,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN14_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ @@ -4238,7 +4256,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN15(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ @@ -4271,7 +4289,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN15_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ @@ -4443,7 +4461,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN16(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ @@ -4476,7 +4494,7 @@ SourceHook::CallClass<T> *SH_GET_CALLCLASS(T *p) __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ { \ - ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>(shptr, value); \ + ::SourceHook::SetOverrideResult<SH_MFHCls(hookname)::RetType>()(shptr, value); \ } #define SH_DECL_MANUALEXTERN16_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ @@ -6737,12 +6755,6 @@ SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Param1, Param2, Param3, Param4, Para namespace SourceHook { - template <class RetType> - void SetOverrideResult(ISourceHook *shptr, const RetType res) - { - *reinterpret_cast<RetType*>(shptr->GetOverrideRetPtr()) = res; - } - // SetOverrideResult used to be implemented like this: // SetOverrideResult(shptr, memfuncptr, return); // normally the compiler can deduce the return type from memfuncptr, but (at least msvc8) failed when it was a reference @@ -6767,6 +6779,14 @@ namespace SourceHook } }; + // For manual hooks: + // The rettype is passed in manually + template <class RetType> + OverrideFunctor<RetType> SetOverrideResult() + { + return OverrideFunctor<RetType>(); + } + template <class Iface, class RetType> OverrideFunctor<RetType> SetOverrideResult(RetType (Iface::*mfp)()) { diff --git a/core/sourcehook/sourcehook_hookmangen.cpp b/core/sourcehook/sourcehook_hookmangen.cpp index ecc1765..287a643 100644 --- a/core/sourcehook/sourcehook_hookmangen.cpp +++ b/core/sourcehook/sourcehook_hookmangen.cpp @@ -1,5 +1,5 @@ /* ======== SourceHook ======== -* Copyright (C) 2004-2009 Metamod:Source Development Team +* Copyright (C) 2004-2010 Metamod:Source Development Team * No warranties of any kind * * License: zlib/libpng diff --git a/core/sourcehook/sourcehook_hookmangen.h b/core/sourcehook/sourcehook_hookmangen.h index 6caf2d4..9e565f7 100644 --- a/core/sourcehook/sourcehook_hookmangen.h +++ b/core/sourcehook/sourcehook_hookmangen.h @@ -1,5 +1,5 @@ /* ======== SourceHook ======== -* Copyright (C) 2004-2008 Metamod:Source Development Team +* Copyright (C) 2004-2010 Metamod:Source Development Team * No warranties of any kind * * License: zlib/libpng diff --git a/core/sourcehook/sourcehook_hookmangen_x86.h b/core/sourcehook/sourcehook_hookmangen_x86.h index d9d15d7..e98393b 100644 --- a/core/sourcehook/sourcehook_hookmangen_x86.h +++ b/core/sourcehook/sourcehook_hookmangen_x86.h @@ -1,6 +1,6 @@ /* ======== SourceHook ======== * vim: set ts=4 : -* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. +* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * No warranties of any kind * * License: zlib/libpng diff --git a/core/sourcehook/sourcehook_impl.h b/core/sourcehook/sourcehook_impl.h index 5d225cc..cf5579e 100644 --- a/core/sourcehook/sourcehook_impl.h +++ b/core/sourcehook/sourcehook_impl.h @@ -1,5 +1,5 @@ /* ======== SourceHook ======== -* Copyright (C) 2004-2008 Metamod:Source Development Team +* Copyright (C) 2004-2010 Metamod:Source Development Team * No warranties of any kind * * License: zlib/libpng @@ -189,6 +189,10 @@ namespace SourceHook { struct CHookContext : IHookContext { + CHookContext() : m_CleanupTask(NULL) + { + } + enum State { State_Born, @@ -224,6 +228,8 @@ namespace SourceHook bool m_CallOrig; + ICleanupTask *m_CleanupTask; + void SkipPaused(List<CHook>::iterator &iter, List<CHook> &list) { while (iter != list.end() && iter->IsPaused()) @@ -238,12 +244,13 @@ namespace SourceHook void *GetOverrideRetPtr(); const void *GetOrigRetPtr(); bool ShouldCallOrig(); + void DoCleanupTaskAndDeleteIt(); }; class CVfnPtrList : public List<CVfnPtr> { public: - CVfnPtr &GetVfnPtr(void *p); + CVfnPtr *GetVfnPtr(void *p); }; typedef CStack<CHookContext> HookContextStack; @@ -259,6 +266,7 @@ namespace SourceHook bool SetHookPaused(int hookid, bool paused); CHookManList::iterator RemoveHookManager(CHookManList::iterator iter); + List<CVfnPtr>::iterator RevertAndRemoveVfnPtr(List<CVfnPtr>::iterator vfnptr_iter); public: CSourceHookImpl(); virtual ~CSourceHookImpl(); @@ -308,7 +316,7 @@ namespace SourceHook void DoRecall(); - IHookContext *SetupHookLoop(IHookManagerInfo *hi, void *vfnptr, void *thisptr, void **origentry, META_RES *statusPtr, + IHookContext *SetupHookLoop(IHookManagerInfo *hi, void *vfnptr, void *thisptr, void **origCallAddr, META_RES *statusPtr, META_RES *prevResPtr, META_RES *curResPtr, const void *origRetPtr, void *overrideRetPtr); void EndContext(IHookContext *pCtx); diff --git a/core/sourcehook/sourcehook_impl_chook.h b/core/sourcehook/sourcehook_impl_chook.h index e1ea76e..2050ed7 100644 --- a/core/sourcehook/sourcehook_impl_chook.h +++ b/core/sourcehook/sourcehook_impl_chook.h @@ -1,5 +1,5 @@ /* ======== SourceHook ======== -* Copyright (C) 2004-2008 Metamod:Source Development Team +* Copyright (C) 2004-2010 Metamod:Source Development Team * No warranties of any kind * * License: zlib/libpng diff --git a/core/sourcehook/sourcehook_impl_chookidman.cpp b/core/sourcehook/sourcehook_impl_chookidman.cpp new file mode 100644 index 0000000..29a3d09 --- /dev/null +++ b/core/sourcehook/sourcehook_impl_chookidman.cpp @@ -0,0 +1,111 @@ +/* ======== SourceHook ======== +* Copyright (C) 2004-2010 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): Pavol "PM OnoTo" Marko +* Contributors: Scott "Damaged Soul" Ehlert +* ============================ +*/ + +#include "sourcehook_impl.h" + +namespace SourceHook +{ + namespace Impl + { + CHookIDManager::CHookIDManager() + { + } + + int CHookIDManager::New(const CProto &proto, int vtbl_offs, int vtbl_idx, void *vfnptr, + void *adjustediface, Plugin plug, int thisptr_offs, ISHDelegate *handler, bool post) + { + Entry tmp(proto, vtbl_offs, vtbl_idx, vfnptr, adjustediface, plug, thisptr_offs, handler, post); + + size_t cursize = m_Entries.size(); + for (size_t i = 0; i < cursize; ++i) + { + if (m_Entries[i].isfree) + { + m_Entries[i] = tmp; + return static_cast<int>(i) + 1; + } + } + + m_Entries.push_back(tmp); + return static_cast<int>(m_Entries.size()); // return size() because hookid = id+1 anyway + } + + bool CHookIDManager::Remove(int hookid) + { + int realid = hookid - 1; + if (realid < 0 || realid >= static_cast<int>(m_Entries.size()) || m_Entries[realid].isfree) + return false; + + m_Entries[realid].isfree = true; + + // :TODO: remove free ids from back sometimes ?? + + return true; + } + + const CHookIDManager::Entry * CHookIDManager::QueryHook(int hookid) + { + int realid = hookid - 1; + if (realid < 0 || realid >= static_cast<int>(m_Entries.size()) || m_Entries[realid].isfree) + return NULL; + + return &m_Entries[realid]; + } + + void CHookIDManager::FindAllHooks(CVector<int> &output, const CProto &proto, int vtbl_offs, + int vtbl_idx, void *adjustediface, Plugin plug, int thisptr_offs, ISHDelegate *handler, bool post) + { + // oh my god, a lot of parameters... + size_t cursize = m_Entries.size(); + for (size_t i = 0; i < cursize; ++i) + { + if (!m_Entries[i].isfree && m_Entries[i].proto == proto && m_Entries[i].vtbl_offs == vtbl_offs && + m_Entries[i].vtbl_idx == vtbl_idx && m_Entries[i].adjustediface == adjustediface && m_Entries[i].plug == plug && + m_Entries[i].thisptr_offs == thisptr_offs && m_Entries[i].handler->IsEqual(handler) && m_Entries[i].post == post) + { + output.push_back(static_cast<int>(i) + 1); + } + } + } + + void CHookIDManager::FindAllHooks(CVector<int> &output) + { + size_t cursize = m_Entries.size(); + for (size_t i = 0; i < cursize; ++i) + { + if (!m_Entries[i].isfree) + output.push_back(static_cast<int>(i) + 1); + } + } + + void CHookIDManager::FindAllHooks(CVector<int> &output, Plugin plug) + { + size_t cursize = m_Entries.size(); + for (size_t i = 0; i < cursize; ++i) + { + if (!m_Entries[i].isfree && m_Entries[i].plug == plug) + output.push_back(static_cast<int>(i) + 1); + } + } + + + void CHookIDManager::RemoveAll(void *vfnptr) + { + size_t cursize = m_Entries.size(); + for (size_t i = 0; i < cursize; ++i) + { + if (!m_Entries[i].isfree && m_Entries[i].vfnptr == vfnptr) + m_Entries[i].isfree = true; + } + } + + } +} diff --git a/core/sourcehook/sourcehook_impl_chookidman.h b/core/sourcehook/sourcehook_impl_chookidman.h index 20dfeba..03f0bc5 100644 --- a/core/sourcehook/sourcehook_impl_chookidman.h +++ b/core/sourcehook/sourcehook_impl_chookidman.h @@ -1,5 +1,5 @@ /* ======== SourceHook ======== -* Copyright (C) 2004-2008 Metamod:Source Development Team +* Copyright (C) 2004-2010 Metamod:Source Development Team * No warranties of any kind * * License: zlib/libpng diff --git a/core/sourcehook/sourcehook_impl_chookmaninfo.cpp b/core/sourcehook/sourcehook_impl_chookmaninfo.cpp new file mode 100644 index 0000000..639b7a2 --- /dev/null +++ b/core/sourcehook/sourcehook_impl_chookmaninfo.cpp @@ -0,0 +1,84 @@ +/* ======== SourceHook ======== +* Copyright (C) 2004-2010 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): Pavol "PM OnoTo" Marko +* Contributors: Scott "Damaged Soul" Ehlert +* ============================ +*/ + +#include "sourcehook_impl.h" + +namespace SourceHook +{ + namespace Impl + { + CHookManager::CHookManager(Plugin ownerPlugin, HookManagerPubFunc pubFunc) + : m_OwnerPlugin(ownerPlugin), m_PubFunc(pubFunc), m_Version(-1) + { + // Query pubfunc + // -> Should call SetInfo and set all the other variables! + if (m_PubFunc(false, this) != 0) + { + // Error! + m_Version = -1; + } + } + + void CHookManager::SetInfo(int hookman_version, int vtbloffs, int vtblidx, + ProtoInfo *proto, void *hookfunc_vfnptr) + { + m_Version = hookman_version; + m_VtblOffs = vtbloffs; + m_VtblIdx = vtblidx; + m_Proto = proto; + m_HookfuncVfnptr = hookfunc_vfnptr; + } + + void CHookManager::Register() + { + m_PubFunc(true, this); + } + + void CHookManager::Unregister() + { + m_PubFunc(true, NULL); + } + + void CHookManager::IncrRef(CVfnPtr *pVfnPtr) + { + m_VfnPtrs.push_back(pVfnPtr); + if (m_VfnPtrs.size() == 1) + Register(); + } + + void CHookManager::DecrRef(CVfnPtr *pVfnPtr) + { + m_VfnPtrs.remove(pVfnPtr); + if (m_VfnPtrs.empty()) + Unregister(); + } + + CHookManager *CHookManList::GetHookMan(Plugin plug, HookManagerPubFunc pubFunc) + { + CHookManager hm(plug, pubFunc); + return GetHookMan(hm); + } + + CHookManager *CHookManList::GetHookMan(CHookManager &hm) + { + iterator iter = find(hm); + if (iter == end()) + { + push_back(hm); + return &(back()); + } + else + { + return &(*iter); + } + } + } +} diff --git a/core/sourcehook/sourcehook_impl_chookmaninfo.h b/core/sourcehook/sourcehook_impl_chookmaninfo.h index 03de9d7..6a805ea 100644 --- a/core/sourcehook/sourcehook_impl_chookmaninfo.h +++ b/core/sourcehook/sourcehook_impl_chookmaninfo.h @@ -1,5 +1,5 @@ /* ======== SourceHook ======== -* Copyright (C) 2004-2008 Metamod:Source Development Team +* Copyright (C) 2004-2010 Metamod:Source Development Team * No warranties of any kind * * License: zlib/libpng @@ -46,7 +46,7 @@ namespace SourceHook }; // *** Interface *** - inline CHookManager(Plugin ownerPlugin, HookManagerPubFunc pubFunc); + CHookManager(Plugin ownerPlugin, HookManagerPubFunc pubFunc); inline bool operator==(const Descriptor &other) const; inline bool operator==(const CHookManager &other) const; @@ -60,11 +60,11 @@ namespace SourceHook inline void *GetHookFunc() const; inline HookManagerPubFunc GetPubFunc() const; - inline void Register(); - inline void Unregister(); + void Register(); + void Unregister(); - inline void IncrRef(CVfnPtr *pVfnPtr); - inline void DecrRef(CVfnPtr *pVfnPtr); + void IncrRef(CVfnPtr *pVfnPtr); + void DecrRef(CVfnPtr *pVfnPtr); List<CVfnPtr*> &GetVfnPtrList() { @@ -79,22 +79,11 @@ namespace SourceHook class CHookManList : public List<CHookManager> { public: - inline CHookManager *GetHookMan(Plugin plug, HookManagerPubFunc pubFunc); - inline CHookManager *GetHookMan(CHookManager &hm); + CHookManager *GetHookMan(Plugin plug, HookManagerPubFunc pubFunc); + CHookManager *GetHookMan(CHookManager &hm); }; - // *** Implementation *** - inline CHookManager::CHookManager(Plugin ownerPlugin, HookManagerPubFunc pubFunc) - : m_OwnerPlugin(ownerPlugin), m_PubFunc(pubFunc), m_Version(-1) - { - // Query pubfunc - // -> Should call SetInfo and set all the other variables! - if (m_PubFunc(false, this) != 0) - { - // Error! - m_Version = -1; - } - } + // *** Implementation **/ inline CHookManager::operator bool() const { @@ -147,50 +136,6 @@ namespace SourceHook { return m_PubFunc; } - - inline void CHookManager::Register() - { - m_PubFunc(true, this); - } - - inline void CHookManager::Unregister() - { - m_PubFunc(true, NULL); - } - - inline void CHookManager::IncrRef(CVfnPtr *pVfnPtr) - { - m_VfnPtrs.push_back(pVfnPtr); - if (m_VfnPtrs.size() == 1) - Register(); - } - - inline void CHookManager::DecrRef(CVfnPtr *pVfnPtr) - { - m_VfnPtrs.remove(pVfnPtr); - if (m_VfnPtrs.empty()) - Unregister(); - } - - inline CHookManager *CHookManList::GetHookMan(Plugin plug, HookManagerPubFunc pubFunc) - { - CHookManager hm(plug, pubFunc); - return GetHookMan(hm); - } - - inline CHookManager *CHookManList::GetHookMan(CHookManager &hm) - { - iterator iter = find(hm); - if (iter == end()) - { - push_back(hm); - return &(back()); - } - else - { - return &(*iter); - } - } } } diff --git a/core/sourcehook/sourcehook_impl_ciface.h b/core/sourcehook/sourcehook_impl_ciface.h index 7f3c069..978c16a 100644 --- a/core/sourcehook/sourcehook_impl_ciface.h +++ b/core/sourcehook/sourcehook_impl_ciface.h @@ -1,5 +1,5 @@ /* ======== SourceHook ======== -* Copyright (C) 2004-2008 Metamod:Source Development Team +* Copyright (C) 2004-2010 Metamod:Source Development Team * No warranties of any kind * * License: zlib/libpng diff --git a/core/sourcehook/sourcehook_impl_cleanuptask.h b/core/sourcehook/sourcehook_impl_cleanuptask.h new file mode 100644 index 0000000..7f3e0fe --- /dev/null +++ b/core/sourcehook/sourcehook_impl_cleanuptask.h @@ -0,0 +1,29 @@ +/* ======== SourceHook ======== +* Copyright (C) 2004-2010 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): Pavol "PM OnoTo" Marko +* ============================ +*/ + +#ifndef __SOURCEHOOK_IMPL_CLEANUPTASK_H__ +#define __SOURCEHOOK_IMPL_CLEANUPTASK_H__ + + +namespace SourceHook +{ + namespace Impl + { + class ICleanupTask + { + public: + virtual void CleanupAndDeleteThis() = 0; + }; + } +} + +// __SOURCEHOOK_IMPL_CLEANUPTASK_H__ +#endif + diff --git a/core/sourcehook/sourcehook_impl_cproto.cpp b/core/sourcehook/sourcehook_impl_cproto.cpp new file mode 100644 index 0000000..ff8af28 --- /dev/null +++ b/core/sourcehook/sourcehook_impl_cproto.cpp @@ -0,0 +1,145 @@ +/* ======== SourceHook ======== +* Copyright (C) 2004-2010 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): Pavol "PM OnoTo" Marko +* ============================ +*/ + +#include "sourcehook_impl.h" + +namespace SourceHook +{ + namespace Impl + { + void CProto::Fill(const ProtoInfo *pProto) + { + if (pProto == NULL) + m_Version = -1; + + m_ParamsPassInfo.clear(); + + if (pProto->paramsPassInfo[0].size == 0) + { + // Version 1 + m_Version = 0; + m_Convention = pProto->convention; + m_NumOfParams = pProto->numOfParams; + + m_RetPassInfo.size = pProto->retPassInfo.size; + m_RetPassInfo.type = pProto->retPassInfo.type; + m_RetPassInfo.flags = GetRealFlags(pProto->retPassInfo); + + m_RetPassInfo.pNormalCtor = NULL; + m_RetPassInfo.pCopyCtor = NULL; + m_RetPassInfo.pDtor = NULL; + m_RetPassInfo.pAssignOperator = NULL; + + + m_ParamsPassInfo.resize(pProto->numOfParams); + + for (int i = 1; i <= pProto->numOfParams; ++i) + { + m_ParamsPassInfo[i-1].size = pProto->paramsPassInfo[i].size; + m_ParamsPassInfo[i-1].type = pProto->paramsPassInfo[i].type; + m_ParamsPassInfo[i-1].flags = GetRealFlags(pProto->paramsPassInfo[i]); + + m_ParamsPassInfo[i-1].pNormalCtor = NULL; + m_ParamsPassInfo[i-1].pCopyCtor = NULL; + m_ParamsPassInfo[i-1].pDtor = NULL; + m_ParamsPassInfo[i-1].pAssignOperator = NULL; + } + } + else if (pProto->paramsPassInfo[0].size == 1) + { + // Version 2 + m_Version = 1; + m_Convention = pProto->convention; + m_NumOfParams = pProto->numOfParams; + + m_RetPassInfo.size = pProto->retPassInfo.size; + m_RetPassInfo.type = pProto->retPassInfo.type; + m_RetPassInfo.flags = pProto->retPassInfo.flags; + + m_RetPassInfo.pNormalCtor = pProto->retPassInfo2.pNormalCtor; + m_RetPassInfo.pCopyCtor = pProto->retPassInfo2.pCopyCtor; + m_RetPassInfo.pDtor = pProto->retPassInfo2.pDtor; + m_RetPassInfo.pAssignOperator = pProto->retPassInfo2.pAssignOperator; + + m_ParamsPassInfo.resize(pProto->numOfParams); + + for (int i = 1; i <= pProto->numOfParams; ++i) + { + m_ParamsPassInfo[i-1].size = pProto->paramsPassInfo[i].size; + m_ParamsPassInfo[i-1].type = pProto->paramsPassInfo[i].type; + m_ParamsPassInfo[i-1].flags = pProto->paramsPassInfo[i].flags; + + m_ParamsPassInfo[i-1].pNormalCtor = pProto->paramsPassInfo2[i].pNormalCtor; + m_ParamsPassInfo[i-1].pCopyCtor = pProto->paramsPassInfo2[i].pCopyCtor; + m_ParamsPassInfo[i-1].pDtor = pProto->paramsPassInfo2[i].pDtor; + m_ParamsPassInfo[i-1].pAssignOperator = pProto->paramsPassInfo2[i].pAssignOperator; + } + } + else + { + // Unknown + m_Version = -1; + } + } + + // Basic compat test + // Other than this, we assume that the plugins know what they're doing + bool CProto::operator == (const CProto &other) const + { + if (m_Version < 0 || other.GetVersion() < 0) + return false; + + if (m_NumOfParams != other.GetNumOfParams()) + return false; + + if (m_Convention != ProtoInfo::CallConv_Unknown && other.GetConvention() != ProtoInfo::CallConv_Unknown && + m_Convention != other.GetConvention()) + return false; + + if (GetRealSize(GetRet()) != GetRealSize(other.GetRet())) + return false; + + for (int i = 0; i < m_NumOfParams; ++i) + { + if (GetRealSize(GetParam(i)) != GetRealSize(other.GetParam(i))) + return false; + if (GetParam(i).type != PassInfo::PassType_Unknown && other.GetParam(i).type != PassInfo::PassType_Unknown) + { + if (GetParam(i).type != other.GetParam(i).type) + return false; + if (GetParam(i).flags != other.GetParam(i).flags) + return false; + } + } + + return true; + } + + bool CProto::ExactlyEqual(const CProto &other) const + { + if (m_Version != other.m_Version || + m_NumOfParams != other.m_NumOfParams || + m_Convention != other.m_Convention || + GetRet() != other.GetRet()) + { + return false; + } + + for (int i = 0; i < m_NumOfParams; ++i) + { + if(GetParam(i) != other.GetParam(i)) + return false; + } + + return true; + } + + } +} diff --git a/core/sourcehook/sourcehook_impl_cproto.h b/core/sourcehook/sourcehook_impl_cproto.h index b11b925..cb436f1 100644 --- a/core/sourcehook/sourcehook_impl_cproto.h +++ b/core/sourcehook/sourcehook_impl_cproto.h @@ -1,5 +1,5 @@ /* ======== SourceHook ======== -* Copyright (C) 2004-2008 Metamod:Source Development Team +* Copyright (C) 2004-2010 Metamod:Source Development Team * No warranties of any kind * * License: zlib/libpng diff --git a/core/sourcehook/sourcehook_impl_cvfnptr.cpp b/core/sourcehook/sourcehook_impl_cvfnptr.cpp new file mode 100644 index 0000000..5159b0c --- /dev/null +++ b/core/sourcehook/sourcehook_impl_cvfnptr.cpp @@ -0,0 +1,253 @@ +/* ======== SourceHook ======== +* Copyright (C) 2004-2010 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): Pavol "PM OnoTo" Marko +* ============================ +*/ + +#include "sourcehook_impl.h" + +namespace SourceHook +{ + namespace Impl + { + CPageAlloc CVfnPtr::ms_AlignedPageAllocator(8); + + CVfnPtr::CVfnPtr(void *ptr) + : m_Ptr(ptr), m_OrigEntry(*reinterpret_cast<void**>(m_Ptr)), + m_OrigCallThunk(NULL) + { + } + + CVfnPtr::~CVfnPtr() + { + if (!m_HookMans.empty()) + m_HookMans.front()->DecrRef(this); + } + + bool CVfnPtr::Init() + { + // Initalize the vfn ptr info object. + + // If we're running on GCC and the original vtable entry is odd + // we have a problem. + // The hook functions use non-virtual member function pointers to + // call the original function (see sourcehook.hxx, SH_SETUP_MFP and SH_CALL_ORIG) + // GCC has the same format for virtual and non-virtual MFPs: + // virtual ones have an odd value as "funcptr" where the offset into the vtable is encoded + // non-virtual ones have the direct function pointer as "funcptr", assuming that it is even + + // When m_OrigEntry is odd, GCC's runtime MFP calling code interpretes it as a virtual + // function call though we want to call the function in a non-virtual way + // (the original function call mechanism between the pre and post hook loop has to bypass + // the virtual calling mechanism in order to call the original function). + +#if SH_COMP==SH_COMP_GCC + if ((((ptrdiff_t)m_OrigEntry) & 1) != 0) + { + // Odd orig entry. + if (SH_PTRSIZE != 4) + { + // We only have code for IA32 atm! + return false; + } + + // Generate a new thunk + m_OrigCallThunk = ms_AlignedPageAllocator.Alloc(5); + ms_AlignedPageAllocator.SetRW(m_OrigCallThunk); + + unsigned char* thunkBase = reinterpret_cast<unsigned char*>(m_OrigCallThunk); + *(thunkBase + 0) = 0xE9; // offset jump, immediate operand + ptrdiff_t *offsetAddr = reinterpret_cast<ptrdiff_t*>(thunkBase + 1); + + // destination = src + offset + 5 + // <=> offset = destination - src - 5 + *offsetAddr = + (reinterpret_cast<unsigned char*>(m_OrigEntry) - thunkBase) - 5; + + ms_AlignedPageAllocator.SetRE(m_OrigCallThunk); + } +#endif + return true; + } + + class CVfnPtrOrigThunkCleanup : public ICleanupTask + { + CPageAlloc *m_Allocator; + void *m_AddrToFree; + + public: + CVfnPtrOrigThunkCleanup(CPageAlloc *allocator, void *addrToFree) : + m_Allocator(allocator), m_AddrToFree(addrToFree) + { + } + + virtual void CleanupAndDeleteThis() + { + m_Allocator->Free(m_AddrToFree); + delete this; + } + }; + + ICleanupTask* CVfnPtr::GetCleanupTask() + { + if (m_OrigCallThunk != NULL) + { + return new CVfnPtrOrigThunkCleanup(&ms_AlignedPageAllocator, m_OrigCallThunk); + } + else + { + return NULL; + } + } + + void* CVfnPtr::GetOrigCallAddr() const + { + if (m_OrigCallThunk) + { + return m_OrigCallThunk; + } + else + { + return m_OrigEntry; + } + } + + bool CVfnPtr::Revert() + { + // Only patch the vfnptr back if the module is still in memory + // If it's not, do not remove stuff like we did before + // First off we did it wrong (shutdown the whole hookman, uh..) and secondly applications may be + // confused by RemoveHook returning false then (yeah, I know, I made this one up, no one checks for RemoveHook error) + if (ModuleInMemory(reinterpret_cast<char*>(m_Ptr), SH_PTRSIZE)) + { + return Patch(m_OrigEntry); + } + else + { + return true; + } + } + + CIface *CVfnPtr::FindIface(void *iface) + { + List<CIface>::iterator iter = m_IfaceList.find(iface); + if (iter == m_IfaceList.end()) + return NULL; + else + return &(*iter); + } + + void CVfnPtr::AddHookMan(CHookManager *pHookMan) + { + List<CHookManager*>::iterator iter; + + // Don't accept invalid hook managers + if (!*pHookMan) + return; + + // Check whether this hook manager already exists; if yes, ignore. + iter = m_HookMans.find(pHookMan); + if (iter != m_HookMans.end()) + return; + + // It doesn't -> add it. Add it to the end of its version group. + for (iter = m_HookMans.begin(); iter != m_HookMans.end(); ++iter) + { + if ((*iter)->GetVersion() < pHookMan->GetVersion()) + break; + } + + bool isBeginning = iter == m_HookMans.begin(); + + m_HookMans.insert(iter, pHookMan); + + if (isBeginning) + { + pHookMan->IncrRef(this); + if (m_HookMans.size() > 1) + { + // If another hookman was used until now but this one is better + // (which it is because it's the first -> it has a higher version) + // -> switch! + + List<CHookManager*>::iterator second = m_HookMans.begin(); + ++second; + + (*second)->DecrRef(this); + } + + // Make sure that this vfnptr points at it + Patch(pHookMan->GetHookFunc()); + } + } + + bool CVfnPtr::HookManRemoved(CHookManager *pHookMan) + { + // Don't accept invalid hook managers + if (!*pHookMan) + return true; + + List<CHookManager*>::iterator iter = m_HookMans.find(pHookMan); + if (iter == m_HookMans.end()) + return true; // Didn't exist here anyway + + if (iter == m_HookMans.begin()) + { + // It is the first one! + pHookMan->DecrRef(this); + m_HookMans.erase(iter); + + if (m_HookMans.empty()) + return false; // No more hookmans -> let SH delete us + + // Activate second -> now first hookman + m_HookMans.front()->IncrRef(this); + Patch(m_HookMans.front()->GetHookFunc()); + } + else + { + m_HookMans.erase(iter); + } + return true; + } + + bool CVfnPtr::Patch(void *newValue) + { + if (!SetMemAccess(m_Ptr, sizeof(void*), SH_MEM_READ | SH_MEM_WRITE)) + { + return false; + } + + *reinterpret_cast<void**>(m_Ptr) = newValue; + + return true; + } + + CIface &CVfnPtr::GetIface(void *iface) + { + List<CIface>::iterator iter = m_IfaceList.find(iface); + if (iter == m_IfaceList.end()) + { + CIface newIface(iface); + if (iface == NULL) + { + m_IfaceList.push_front(newIface); + return m_IfaceList.front(); + } + else + { + m_IfaceList.push_back(newIface); + return m_IfaceList.back(); + } + } + else + { + return *iter; + } + } + } +} diff --git a/core/sourcehook/sourcehook_impl_cvfnptr.h b/core/sourcehook/sourcehook_impl_cvfnptr.h index edb1c7c..1575728 100644 --- a/core/sourcehook/sourcehook_impl_cvfnptr.h +++ b/core/sourcehook/sourcehook_impl_cvfnptr.h @@ -1,5 +1,5 @@ /* ======== SourceHook ======== -* Copyright (C) 2004-2008 Metamod:Source Development Team +* Copyright (C) 2004-2010 Metamod:Source Development Team * No warranties of any kind * * License: zlib/libpng @@ -13,6 +13,8 @@ #include "sh_list.h" #include "sh_memory.h" +#include "sh_pagealloc.h" +#include "sourcehook_impl_cleanuptask.h" namespace SourceHook { @@ -20,9 +22,12 @@ namespace SourceHook { class CVfnPtr { + static CPageAlloc ms_AlignedPageAllocator; + // *** Data *** void *m_Ptr; void *m_OrigEntry; + void *m_OrigCallThunk; // See Init() method List<CHookManager*> m_HookMans; List<CIface> m_IfaceList; @@ -31,17 +36,21 @@ namespace SourceHook typedef void* Descriptor; // *** Interface *** - inline CVfnPtr(void *ptr); - inline ~CVfnPtr(); + CVfnPtr(void *ptr); + ~CVfnPtr(); + bool Init(); inline bool operator==(const Descriptor &other); inline void *GetPtr() const; inline void *GetOrigEntry() const; + void *GetOrigCallAddr() const; inline List<CIface> &GetIfaceList(); inline const List<CIface> &GetIfaceList() const; - inline CIface *FindIface(void *iface); + CIface *FindIface(void *iface); CIface &GetIface(void *iface); bool Patch(void *newValue); - inline bool Revert(); + bool Revert(); + + ICleanupTask *GetCleanupTask(); void AddHookMan(CHookManager *pHookMan); // If this returns false, it means that there is no hook manager left @@ -50,16 +59,6 @@ namespace SourceHook }; // *** Implementation *** - inline CVfnPtr::CVfnPtr(void *ptr) - : m_Ptr(ptr), m_OrigEntry(*reinterpret_cast<void**>(m_Ptr)) - { - } - - inline CVfnPtr::~CVfnPtr() - { - if (!m_HookMans.empty()) - m_HookMans.front()->DecrRef(this); - } inline bool CVfnPtr::operator==(const Descriptor &other) { @@ -85,31 +84,6 @@ namespace SourceHook { return m_IfaceList; } - - inline bool CVfnPtr::Revert() - { - // Only patch the vfnptr back if the module is still in memory - // If it's not, do not remove stuff like we did before - // First off we did it wrong (shutdown the whole hookman, uh..) and secondly applications may be - // confused by RemoveHook returning false then (yeah, I know, I made this one up, no one checks for RemoveHook error) - if (ModuleInMemory(reinterpret_cast<char*>(m_Ptr), SH_PTRSIZE)) - { - return Patch(m_OrigEntry); - } - else - { - return true; - } - } - - inline CIface *CVfnPtr::FindIface(void *iface) - { - List<CIface>::iterator iter = m_IfaceList.find(iface); - if (iter == m_IfaceList.end()) - return NULL; - else - return &(*iter); - } } } diff --git a/core/sourcehook/sourcehook_pibuilder.h b/core/sourcehook/sourcehook_pibuilder.h index df9e7a5..7b88c00 100644 --- a/core/sourcehook/sourcehook_pibuilder.h +++ b/core/sourcehook/sourcehook_pibuilder.h @@ -1,5 +1,5 @@ /* ======== SourceHook ======== -* Copyright (C) 2004-2008 Metamod:Source Development Team +* Copyright (C) 2004-2010 Metamod:Source Development Team * No warranties of any kind * * License: zlib/libpng diff --git a/core/sourcehook/test/Makefile b/core/sourcehook/test/Makefile index e85f092..d5d4c39 100644 --- a/core/sourcehook/test/Makefile +++ b/core/sourcehook/test/Makefile @@ -9,8 +9,8 @@ INCLUDE = -I. -I.. MAX_PARAMS=20 BINARY = sourcehook_test -OBJECTS = main.cpp sourcehook.cpp sourcehook_hookmangen.cpp $(shell ls -t test*.cpp) -HEADERS = ../sh_list.h ../sh_tinyhash.h ../sh_memory.h ../sh_string.h ../sh_vector.h ../sourcehook_impl.h ../FastDelegate.h ../sourcehook.h ../sh_memfuncinfo.h +OBJECTS = main.cpp sourcehook.cpp sourcehook_hookmangen.cpp sourcehook_impl_chookmaninfo.cpp sourcehook_impl_chookidman.cpp sourcehook_impl_cproto.cpp sourcehook_impl_cvfnptr.cpp $(shell ls -t test*.cpp) +HEADERS = ../sh_list.h ../sh_tinyhash.h ../sh_memory.h ../sh_string.h ../sh_vector.h ../sourcehook_impl.h ../FastDelegate.h ../sourcehook.h ../sh_memfuncinfo.h ../sh_pagealloc.h ifeq "$(DEBUG)" "true" BIN_DIR = Debug @@ -48,10 +48,18 @@ all: mkdir -p $(BIN_DIR) ln -sf ../sourcehook.cpp ln -sf ../sourcehook_hookmangen.cpp + ln -sf ../sourcehook_impl_chookidman.cpp + ln -sf ../sourcehook_impl_chookmaninfo.cpp + ln -sf ../sourcehook_impl_cproto.cpp + ln -sf ../sourcehook_impl_cvfnptr.cpp $(MAKE) $(BINARY) rm -f $(BINARY) rm -f sourcehook.cpp rm -f sourcehook_hookmangen.cpp + rm -f sourcehook_impl_chookidman.cpp + rm -f sourcehook_impl_chookmaninfo.cpp + rm -f sourcehook_impl_cproto.cpp + rm -f sourcehook_impl_cvfnptr.cpp ln -sf $(BIN_DIR)/$(BINARY) $(BINARY) diff --git a/core/sourcehook/test/main.cpp b/core/sourcehook/test/main.cpp index 9b2ba82..dc1fb88 100644 --- a/core/sourcehook/test/main.cpp +++ b/core/sourcehook/test/main.cpp @@ -49,6 +49,7 @@ DECL_TEST(RefRet); DECL_TEST(VPHooks); DECL_TEST(CPageAlloc); // in testhookmangen.cpp DECL_TEST(HookManGen); +DECL_TEST(OddThunks); int main(int argc, char *argv[]) { @@ -73,6 +74,7 @@ int main(int argc, char *argv[]) DO_TEST(VPHooks); DO_TEST(CPageAlloc); DO_TEST(HookManGen); + DO_TEST(OddThunks); cout << endl << "----" << endl << "Passed: " << passed << endl << "Failed: " << failed << endl; cout << "Total: " << passed + failed << endl; diff --git a/core/sourcehook/test/test.sln b/core/sourcehook/test/test.sln new file mode 100644 index 0000000..327a99a --- /dev/null +++ b/core/sourcehook/test/test.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test.vcproj", "{456BBA64-FF14-4292-8443-3BA79E4D84CC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug_NoDebugRuntimeLib|Win32 = Debug_NoDebugRuntimeLib|Win32 + Debug|Win32 = Debug|Win32 + DebugOpt|Win32 = DebugOpt|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {456BBA64-FF14-4292-8443-3BA79E4D84CC}.Debug_NoDebugRuntimeLib|Win32.ActiveCfg = Debug_NoDebugRuntimeLib|Win32 + {456BBA64-FF14-4292-8443-3BA79E4D84CC}.Debug_NoDebugRuntimeLib|Win32.Build.0 = Debug_NoDebugRuntimeLib|Win32 + {456BBA64-FF14-4292-8443-3BA79E4D84CC}.Debug|Win32.ActiveCfg = Debug|Win32 + {456BBA64-FF14-4292-8443-3BA79E4D84CC}.Debug|Win32.Build.0 = Debug|Win32 + {456BBA64-FF14-4292-8443-3BA79E4D84CC}.DebugOpt|Win32.ActiveCfg = DebugOpt|Win32 + {456BBA64-FF14-4292-8443-3BA79E4D84CC}.DebugOpt|Win32.Build.0 = DebugOpt|Win32 + {456BBA64-FF14-4292-8443-3BA79E4D84CC}.Release|Win32.ActiveCfg = Release|Win32 + {456BBA64-FF14-4292-8443-3BA79E4D84CC}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/core/sourcehook/test/test.vcproj b/core/sourcehook/test/test.vcproj new file mode 100644 index 0000000..4e937b6 --- /dev/null +++ b/core/sourcehook/test/test.vcproj @@ -0,0 +1,619 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="9,00" + Name="test" + ProjectGUID="{456BBA64-FF14-4292-8443-3BA79E4D84CC}" + RootNamespace="test" + Keyword="Win32Proj" + TargetFrameworkVersion="131072" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="Debug" + IntermediateDirectory="Debug" + ConfigurationType="1" + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + CharacterSet="2" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + FavorSizeOrSpeed="0" + AdditionalIncludeDirectories="../..;.." + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;SH_DEBUG;_CRT_SECURE_NO_DEPRECATE" + StringPooling="true" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + EnableFunctionLevelLinking="true" + RuntimeTypeInfo="true" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="true" + DebugInformationFormat="4" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + OutputFile="$(OutDir)/test.exe" + LinkIncremental="2" + GenerateDebugInformation="true" + ProgramDatabaseFile="$(OutDir)/test.pdb" + SubSystem="1" + RandomizedBaseAddress="1" + DataExecutionPrevention="0" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="Release" + IntermediateDirectory="Release" + ConfigurationType="1" + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + CharacterSet="2" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="3" + InlineFunctionExpansion="1" + FavorSizeOrSpeed="2" + OmitFramePointers="true" + AdditionalIncludeDirectories="../..;.." + PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE" + StringPooling="true" + RuntimeLibrary="0" + EnableFunctionLevelLinking="true" + RuntimeTypeInfo="true" + UsePrecompiledHeader="0" + BrowseInformation="0" + WarningLevel="3" + SuppressStartupBanner="true" + Detect64BitPortabilityProblems="true" + DebugInformationFormat="3" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + OutputFile="$(OutDir)/test.exe" + LinkIncremental="1" + GenerateDebugInformation="true" + GenerateMapFile="true" + MapExports="true" + SubSystem="1" + OptimizeReferences="2" + EnableCOMDATFolding="2" + RandomizedBaseAddress="1" + DataExecutionPrevention="0" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="DebugOpt|Win32" + OutputDirectory="DebugOpt" + IntermediateDirectory="DebugOpt" + ConfigurationType="1" + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + CharacterSet="2" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="3" + InlineFunctionExpansion="1" + EnableIntrinsicFunctions="false" + FavorSizeOrSpeed="2" + OmitFramePointers="true" + AdditionalIncludeDirectories=".." + PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE" + StringPooling="true" + MinimalRebuild="false" + BasicRuntimeChecks="0" + RuntimeLibrary="0" + EnableFunctionLevelLinking="true" + RuntimeTypeInfo="true" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="true" + DebugInformationFormat="3" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + OutputFile="$(OutDir)/test.exe" + LinkIncremental="2" + GenerateDebugInformation="true" + ProgramDatabaseFile="$(OutDir)/test.pdb" + SubSystem="1" + RandomizedBaseAddress="1" + DataExecutionPrevention="0" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Debug_NoDebugRuntimeLib|Win32" + OutputDirectory="Debug_NoDebugRuntimeLib" + IntermediateDirectory="Debug_NoDebugRuntimeLib" + ConfigurationType="1" + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + CharacterSet="2" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + FavorSizeOrSpeed="0" + AdditionalIncludeDirectories="../..;.." + PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE" + StringPooling="true" + MinimalRebuild="true" + ExceptionHandling="1" + BasicRuntimeChecks="3" + RuntimeLibrary="0" + EnableFunctionLevelLinking="true" + RuntimeTypeInfo="true" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="true" + DebugInformationFormat="4" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + OutputFile="$(OutDir)/test.exe" + LinkIncremental="2" + GenerateDebugInformation="true" + ProgramDatabaseFile="$(OutDir)/test.pdb" + SubSystem="1" + RandomizedBaseAddress="1" + DataExecutionPrevention="0" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm" + > + <Filter + Name="SourceHook" + > + <File + RelativePath="..\..\sourcehook.cpp" + > + </File> + <File + RelativePath="..\..\sourcehook_hookmangen.cpp" + > + </File> + <File + RelativePath="..\..\sourcehook_impl_chookidman.cpp" + > + </File> + <File + RelativePath="..\..\sourcehook_impl_chookmaninfo.cpp" + > + </File> + <File + RelativePath="..\..\sourcehook_impl_cproto.cpp" + > + </File> + <File + RelativePath="..\..\sourcehook_impl_cvfnptr.cpp" + > + </File> + </Filter> + <Filter + Name="TestTools" + > + <File + RelativePath="..\main.cpp" + > + </File> + <File + RelativePath="..\test1.cpp" + > + </File> + <File + RelativePath="..\test2.cpp" + > + </File> + <File + RelativePath="..\test3.cpp" + > + </File> + <File + RelativePath="..\test4.cpp" + > + </File> + <File + RelativePath="..\testbail.cpp" + > + </File> + <File + RelativePath="..\testbail2.cpp" + > + </File> + <File + RelativePath="..\testhookmangen.cpp" + > + </File> + <File + RelativePath="..\testlist.cpp" + > + </File> + <File + RelativePath="..\testmanual.cpp" + > + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + GeneratePreprocessedFile="0" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\testmulti.cpp" + > + </File> + <File + RelativePath="..\testoddthunks.cpp" + > + </File> + <File + RelativePath="..\testrecall.cpp" + > + </File> + <File + RelativePath="..\testreentr.cpp" + > + </File> + <File + RelativePath="..\testref.cpp" + > + </File> + <File + RelativePath="..\testrefret.cpp" + > + </File> + <File + RelativePath="..\testvphooks.cpp" + > + </File> + </Filter> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl;inc" + > + <Filter + Name="TestTools" + > + <File + RelativePath="..\testbail.h" + > + </File> + <File + RelativePath="..\testevents.h" + > + </File> + <File + RelativePath="..\testhookmangen.h" + > + </File> + </Filter> + <Filter + Name="SourceHook" + > + <File + RelativePath="..\..\sh_list.h" + > + </File> + <File + RelativePath="..\..\sh_memfuncinfo.h" + > + </File> + <File + RelativePath="..\..\sh_memory.h" + > + </File> + <File + RelativePath="..\..\sh_pagealloc.h" + > + </File> + <File + RelativePath="..\..\sh_stack.h" + > + </File> + <File + RelativePath="..\..\sh_string.h" + > + </File> + <File + RelativePath="..\..\sh_tinyhash.h" + > + </File> + <File + RelativePath="..\..\sh_vector.h" + > + </File> + <File + RelativePath="..\..\sourcehook.h" + > + </File> + <File + RelativePath="..\..\sourcehook_hookmangen.h" + > + </File> + <File + RelativePath="..\..\sourcehook_hookmangen_x86.h" + > + </File> + <File + RelativePath="..\..\sourcehook_impl.h" + > + </File> + <File + RelativePath="..\..\sourcehook_impl_chook.h" + > + </File> + <File + RelativePath="..\..\sourcehook_impl_chookidman.h" + > + </File> + <File + RelativePath="..\..\sourcehook_impl_chookmaninfo.h" + > + </File> + <File + RelativePath="..\..\sourcehook_impl_ciface.h" + > + </File> + <File + RelativePath="..\..\sourcehook_impl_cleanuptask.h" + > + </File> + <File + RelativePath="..\..\sourcehook_impl_cproto.h" + > + </File> + <File + RelativePath="..\..\sourcehook_impl_cvfnptr.h" + > + </File> + <File + RelativePath="..\..\sourcehook_pibuilder.h" + > + </File> + <File + RelativePath="..\sourcehook_test.h" + > + </File> + <Filter + Name="generate" + > + <File + RelativePath="..\..\generate\FastDelegate.hxx" + > + </File> + <File + RelativePath="..\..\generate\sh_memfuncinfo.hxx" + > + </File> + <File + RelativePath="..\..\generate\sourcehook.hxx" + > + <FileConfiguration + Name="Debug_NoDebugRuntimeLib|Win32" + > + <Tool + Name="VCCustomBuildTool" + CommandLine="echo on
pushd ..\..\generate
shworker.exe iter sourcehook.hxx sourcehook.h 16
copy sourcehook.h ..\sourcehook.h
popd
" + Outputs="..\..\sourcehook.h" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\testhookmangen.hxx" + > + </File> + </Filter> + </Filter> + </Filter> + <Filter + Name="Resource Files" + Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" + > + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/core/sourcehook/test/testoddthunks.cpp b/core/sourcehook/test/testoddthunks.cpp new file mode 100644 index 0000000..c0e3917 --- /dev/null +++ b/core/sourcehook/test/testoddthunks.cpp @@ -0,0 +1,163 @@ +#include <string> +#include "sourcehook_test.h" +#include "sh_pagealloc.h" +#include "testevents.h" + +namespace +{ + StateList g_States; + SourceHook::ISourceHook *g_SHPtr; + SourceHook::Plugin g_PLID; + + MAKE_STATE(State_Func_Called); + MAKE_STATE(State_Pre1_Called); + MAKE_STATE(State_Pre2_Called); + + int g_CallNumber; + + class Test + { + public: + virtual void Func() + { + ADD_STATE(State_Func_Called); + } + }; + + Test *g_pInst; + + void Handler_Func_Pre1() + { + ADD_STATE(State_Pre1_Called); + } + + SH_DECL_HOOK0_void(Test, Func, SH_NOATTRIB, 0); + + void Handler_Func_Pre2() + { + ADD_STATE(State_Pre2_Called); + + ++g_CallNumber; + if (g_CallNumber == 2) + { + // REMOVE ourselves + SH_REMOVE_HOOK(Test, Func, g_pInst, SH_STATIC(Handler_Func_Pre1), false); + SH_REMOVE_HOOK(Test, Func, g_pInst, SH_STATIC(Handler_Func_Pre2), false); + } + + // Call again. + g_pInst->Func(); + } + + Test *MyInstanceFactory() + { + return new Test; + } + + SourceHook::CPageAlloc g_ThunkAllocator(2); + void *g_OddThunkMemory = NULL; + void *g_OddThunk = NULL; + + // Guarantees that Func() + // has a vtable entry showing to an ODD address + void PatchFuncWithOddThunk() + { + g_OddThunkMemory = g_ThunkAllocator.Alloc(10); + unsigned char* base = reinterpret_cast<unsigned char*>(g_OddThunkMemory); + + if (((ptrdiff_t)base) & 1) + { + // ODD, ok. + } + else + { + // EVEN. make odd. + base += 1; + } + + // Get vtable entry pointer + SourceHook::MemFuncInfo info = {true, -1, 0, 0}; + SourceHook::GetFuncInfo(g_pInst, &Test::Func, info); + + void *adjustediface = NULL; + void **cur_vtptr = NULL; + void **cur_vfnptr = NULL; + + adjustediface = reinterpret_cast<void*>(reinterpret_cast<char*>(g_pInst) + info.thisptroffs); + + cur_vtptr = *reinterpret_cast<void***>( + reinterpret_cast<char*>(adjustediface) + info.vtbloffs); + cur_vfnptr = reinterpret_cast<void**>(cur_vtptr + info.vtblindex); + + + // Original function + void *origEntry = *cur_vfnptr; + + // Now generate the jump code + g_ThunkAllocator.SetRW(g_OddThunkMemory); + + *(base + 0) = 0xE9; // offset jump, immediate operand + ptrdiff_t *offsetAddr = reinterpret_cast<ptrdiff_t*>(base + 1); + + // destination = src + offset + 5 + // <=> offset = destination - src - 5 + *offsetAddr = + (reinterpret_cast<unsigned char*>(origEntry) - base) - 5; + + g_ThunkAllocator.SetRE(g_OddThunkMemory); + + g_OddThunk = reinterpret_cast<void*>(base); + + // Now set the odd thunk as new vtable entry + SourceHook::SetMemAccess((void*)cur_vfnptr, sizeof(void*), SH_MEM_READ | SH_MEM_WRITE); + *cur_vfnptr = g_OddThunk; + } + + void FreeOddThunk() + { + g_ThunkAllocator.Free(g_OddThunkMemory); + g_OddThunk = NULL; + } +} + +bool TestOddThunks(std::string &error) +{ + GET_SHPTR(g_SHPtr); + g_PLID = 1337; + + g_CallNumber = 0; + + g_pInst = MyInstanceFactory(); + + PatchFuncWithOddThunk(); + + SH_ADD_HOOK(Test, Func, g_pInst, SH_STATIC(Handler_Func_Pre1), false); + SH_ADD_HOOK(Test, Func, g_pInst, SH_STATIC(Handler_Func_Pre2), false); + + g_pInst->Func(); + + CHECK_STATES((&g_States, + // FIRST func() call + new State_Pre1_Called(), + new State_Pre2_Called(), // calls Func() again + + // SECOND func() call + new State_Pre1_Called(), + new State_Pre2_Called(), // removes hooks and calls Func() again + + // THIRD func() call + new State_Func_Called(), + + // SECOND func() call + new State_Func_Called(), + + // FIRST func() call + new State_Func_Called(), + NULL), "Part 1"); + + delete g_pInst; + FreeOddThunk(); + + return true; +} + diff --git a/core/sourcehook/test/testrefret.cpp b/core/sourcehook/test/testrefret.cpp index 597c0bd..f47c0df 100644 --- a/core/sourcehook/test/testrefret.cpp +++ b/core/sourcehook/test/testrefret.cpp @@ -49,6 +49,11 @@ namespace } }; + SH_DECL_HOOK0(Test, Func1, SH_NOATTRIB, 0, int&); + SH_DECL_MANUALHOOK0(Manual_Test_Func1, 0, 0, 0, int&); + SH_DECL_HOOK1(Test, Func2, SH_NOATTRIB, 0, const int&, int); + SH_DECL_MANUALHOOK1(Manual_Test_Func2, 1, 0, 0, const int&, int); + class CHook { public: @@ -76,12 +81,18 @@ namespace RETURN_META_VALUE(MRES_OVERRIDE, m_Var); } - virtual const int& Func2_Pre1(int p1) + virtual const int& Func2_PreRecall_OverrideRet_Normal(int p1) { ADD_STATE(State_Func2_Pre1(p1, &m_Var)); RETURN_META_VALUE_NEWPARAMS(MRES_OVERRIDE, m_Var, static_cast<const int& (Test::*)(int)>(&Test::Func2), (1337)); } + virtual const int& Func2_PreRecall_OverrideRet_Manual(int p1) + { + ADD_STATE(State_Func2_Pre1(p1, &m_Var)); + RETURN_META_VALUE_MNEWPARAMS(MRES_OVERRIDE, m_Var, Manual_Test_Func2, (1337)); + } + virtual const int& Func2_Post1(int p1) { ADD_STATE(State_Func2_Post1(p1, &META_RESULT_ORIG_RET(int&), &META_RESULT_OVERRIDE_RET(int&))); @@ -89,117 +100,220 @@ namespace } }; - SH_DECL_HOOK0(Test, Func1, SH_NOATTRIB, 0, int&); - SH_DECL_HOOK1(Test, Func2, SH_NOATTRIB, 0, const int&, int); - Test *MyTestFactory() { return new Test; } } -bool TestRefRet(std::string &error) +class TesterRefRet { - GET_SHPTR(g_SHPtr); - g_PLID = 1; - - Test *pTest = MyTestFactory(); - CAutoPtrDestruction<Test> apd(pTest); +public: + Test *pTest; CHook hook; - int &ret1 = pTest->Func1(); - ADD_STATE(State_Func1_Ret(&ret1)); + TesterRefRet() + { + pTest = NULL; + } - CHECK_STATES((&g_States, - new State_Func1(&pTest->m_Var1), - new State_Func1_Ret(&pTest->m_Var1), - NULL), "Part 1"); + bool doTests(std::string &error) + { + GET_SHPTR(g_SHPtr); + g_PLID = 1; - // Now add Func1_Pre1, which supercedes and returns hook.m_Var - SH_ADD_HOOK(Test, Func1, pTest, SH_MEMBER(&hook, &CHook::Func1_Pre1), false); + pTest = MyTestFactory(); + CAutoPtrDestruction<Test> apd(pTest); - int &ret2 = pTest->Func1(); - ADD_STATE(State_Func1_Ret(&ret2)); - - CHECK_STATES((&g_States, - new State_Func1_Pre1(&hook.m_Var), // Pre1 says that it's going to override with hook.m_Var - new State_Func1(&pTest->m_Var1), // Function says that it's going to return pTest->m_Var1 - new State_Func1_Ret(&hook.m_Var), // hook.m_Var is returned - NULL), "Part 2"); + int &ret1 = pTest->Func1(); + ADD_STATE(State_Func1_Ret(&ret1)); - // Now add Func1_Post1, which only reports orig ret and override ret - SH_ADD_HOOK(Test, Func1, pTest, SH_MEMBER(&hook, &CHook::Func1_Post1), true); + CHECK_STATES((&g_States, + new State_Func1(&pTest->m_Var1), + new State_Func1_Ret(&pTest->m_Var1), + NULL), "Part 1"); - int &ret3 = pTest->Func1(); - ADD_STATE(State_Func1_Ret(&ret3)); - - CHECK_STATES((&g_States, - new State_Func1_Pre1(&hook.m_Var), // Pre1 says that it's going to override with hook.m_Var - new State_Func1(&pTest->m_Var1), // Function says that it's going to return pTest->m_Var1 - new State_Func1_Post1(&pTest->m_Var1, &hook.m_Var), // origret(=p1) is what it wanted to - // return, overrideret(=p2) is pre1's var - new State_Func1_Ret(&hook.m_Var), // hook.m_Var is returned - NULL), "Part 3"); + // Now add Func1_Pre1, which supercedes and returns hook.m_Var + AddHook__Test_Func1__Func1_Pre(); - // Now add Func1_Pre2, which supercedes and returns g_Var (it also sets the override ret from pre1 to 1337) - // and add Func1_Post2, which overrides and returns hook.m_Var again. + int &ret2 = pTest->Func1(); + ADD_STATE(State_Func1_Ret(&ret2)); + + CHECK_STATES((&g_States, + new State_Func1_Pre1(&hook.m_Var), // Pre1 says that it's going to override with hook.m_Var + new State_Func1(&pTest->m_Var1), // Function says that it's going to return pTest->m_Var1 + new State_Func1_Ret(&hook.m_Var), // hook.m_Var is returned + NULL), "Part 2"); - SH_ADD_HOOK(Test, Func1, pTest, SH_MEMBER(&hook, &CHook::Func1_Pre2), false); - SH_ADD_HOOK(Test, Func1, pTest, SH_MEMBER(&hook, &CHook::Func1_Post2), true); + // Now add Func1_Post1, which only reports orig ret and override ret + AddHook__Test_Func1__Func1_Post(); - int &ret4 = pTest->Func1(); - ADD_STATE(State_Func1_Ret(&ret4)); + int &ret3 = pTest->Func1(); + ADD_STATE(State_Func1_Ret(&ret3)); + + CHECK_STATES((&g_States, + new State_Func1_Pre1(&hook.m_Var), // Pre1 says that it's going to override with hook.m_Var + new State_Func1(&pTest->m_Var1), // Function says that it's going to return pTest->m_Var1 + new State_Func1_Post1(&pTest->m_Var1, &hook.m_Var), // origret(=p1) is what it wanted to + // return, overrideret(=p2) is pre1's var + new State_Func1_Ret(&hook.m_Var), // hook.m_Var is returned + NULL), "Part 3"); - CHECK_STATES((&g_States, - new State_Func1_Pre1(&hook.m_Var), // Pre1 says that it's going to override with hook.m_Var - new State_Func1_Pre2(MRES_OVERRIDE, // current status - &hook.m_Var, // override ret (which it set to 1337) - &g_Var), // what it's going to ret, AND supercede with + // Now add Func1_Pre2, which supercedes and returns g_Var (it also sets the override ret from pre1 to 1337) + // and add Func1_Post2, which overrides and returns hook.m_Var again. - new State_Func1_Post1(&g_Var, &g_Var), // origret(=p1) is what pre2 superceded with, - // so overrideret(=p2) has to be the same - new State_Func1_Post2(&hook.m_Var), // post2 is going to override with hook.m_Var again - new State_Func1_Ret(&hook.m_Var), // ==>>> hook.m_Var is returned - NULL), "Part 4"); + AddHook__Test_Func1__Func1_Pre2(); + AddHook__Test_Func1__Func1_Post2(); - CHECK_COND(hook.m_Var == 1337, "Part 4.1"); - - // Through a callclass - SourceHook::CallClass<Test> *cc1 = SH_GET_CALLCLASS(pTest); - int &ret5 = SH_CALL(cc1, &Test::Func1)(); - ADD_STATE(State_Func1_Ret(&ret5)); + int &ret4 = pTest->Func1(); + ADD_STATE(State_Func1_Ret(&ret4)); - CHECK_STATES((&g_States, - new State_Func1(&pTest->m_Var1), - new State_Func1_Ret(&pTest->m_Var1), - NULL), "Part 5"); + CHECK_STATES((&g_States, + new State_Func1_Pre1(&hook.m_Var), // Pre1 says that it's going to override with hook.m_Var + new State_Func1_Pre2(MRES_OVERRIDE, // current status + &hook.m_Var, // override ret (which it set to 1337) + &g_Var), // what it's going to ret, AND supercede with - SH_RELEASE_CALLCLASS(cc1); + new State_Func1_Post1(&g_Var, &g_Var), // origret(=p1) is what pre2 superceded with, + // so overrideret(=p2) has to be the same + new State_Func1_Post2(&hook.m_Var), // post2 is going to override with hook.m_Var again + new State_Func1_Ret(&hook.m_Var), // ==>>> hook.m_Var is returned + NULL), "Part 4"); - //////////////////////////////////////////////////////////////////////////////////////// - // Func2 tests - const int &ret21 = pTest->Func2(500); - ADD_STATE(State_Func2_Ret(&ret21)); + CHECK_COND(hook.m_Var == 1337, "Part 4.1"); + + // Through a callclass + SourceHook::CallClass<Test> *cc1 = SH_GET_CALLCLASS(pTest); + int &ret5 = SH_CALL(cc1, &Test::Func1)(); + ADD_STATE(State_Func1_Ret(&ret5)); - CHECK_STATES((&g_States, - new State_Func2(500, &pTest->m_Var2), - new State_Func2_Ret(&pTest->m_Var2), - NULL), "Part 6"); + CHECK_STATES((&g_States, + new State_Func1(&pTest->m_Var1), + new State_Func1_Ret(&pTest->m_Var1), + NULL), "Part 5"); - SH_ADD_HOOK(Test, Func2, pTest, SH_MEMBER(&hook, &CHook::Func2_Pre1), false); - SH_ADD_HOOK(Test, Func2, pTest, SH_MEMBER(&hook, &CHook::Func2_Post1), true); + SH_RELEASE_CALLCLASS(cc1); - const int &ret22 = pTest->Func2(500); - ADD_STATE(State_Func2_Ret(&ret22)); + //////////////////////////////////////////////////////////////////////////////////////// + // Func2 tests + const int &ret21 = pTest->Func2(500); + ADD_STATE(State_Func2_Ret(&ret21)); - CHECK_STATES((&g_States, - new State_Func2_Pre1(500, &hook.m_Var), // p1 was 500; it's going to override with hook.m_Var; and also change p1 to 1337 - new State_Func2(1337, &pTest->m_Var2), // p1 was 1337; it's going to ret pTest->m_Var2 - new State_Func2_Post1(1337, // p1 was 1337 - &pTest->m_Var2, // orig ret was pTest->m_Var2 - &hook.m_Var), // override ret was hook.m_Var - new State_Func2_Ret(&hook.m_Var), // really returned hook.m_Var - NULL), "Part 7"); - - return true; + CHECK_STATES((&g_States, + new State_Func2(500, &pTest->m_Var2), + new State_Func2_Ret(&pTest->m_Var2), + NULL), "Part 6"); + + AddHook__Test_Func2__Func2_Pre1(); + AddHook__Test_Func2__Func2_Post1(); + + const int &ret22 = pTest->Func2(500); + ADD_STATE(State_Func2_Ret(&ret22)); + + CHECK_STATES((&g_States, + new State_Func2_Pre1(500, &hook.m_Var), // p1 was 500; it's going to override with hook.m_Var; and also change p1 to 1337 + new State_Func2(1337, &pTest->m_Var2), // p1 was 1337; it's going to ret pTest->m_Var2 + new State_Func2_Post1(1337, // p1 was 1337 + &pTest->m_Var2, // orig ret was pTest->m_Var2 + &hook.m_Var), // override ret was hook.m_Var + new State_Func2_Ret(&hook.m_Var), // really returned hook.m_Var + NULL), "Part 7"); + + return true; + } + + virtual void AddHook__Test_Func1__Func1_Pre() = 0; + virtual void AddHook__Test_Func1__Func1_Post() = 0; + + virtual void AddHook__Test_Func1__Func1_Pre2() = 0; + virtual void AddHook__Test_Func1__Func1_Post2() = 0; + + virtual void AddHook__Test_Func2__Func2_Pre1() = 0; + virtual void AddHook__Test_Func2__Func2_Post1() = 0; +}; + +class TesterRefRetNonManual : public TesterRefRet +{ +public: + void AddHook__Test_Func1__Func1_Pre() + { + SH_ADD_HOOK(Test, Func1, pTest, SH_MEMBER(&hook, &CHook::Func1_Pre1), false); + } + + void AddHook__Test_Func1__Func1_Post() + { + SH_ADD_HOOK(Test, Func1, pTest, SH_MEMBER(&hook, &CHook::Func1_Post1), true); + } + + void AddHook__Test_Func1__Func1_Pre2() + { + SH_ADD_HOOK(Test, Func1, pTest, SH_MEMBER(&hook, &CHook::Func1_Pre2), false); + } + + void AddHook__Test_Func1__Func1_Post2() + { + SH_ADD_HOOK(Test, Func1, pTest, SH_MEMBER(&hook, &CHook::Func1_Post2), true); + } + + void AddHook__Test_Func2__Func2_Pre1() + { + SH_ADD_HOOK(Test, Func2, pTest, SH_MEMBER(&hook, &CHook::Func2_PreRecall_OverrideRet_Normal), false); + } + + void AddHook__Test_Func2__Func2_Post1() + { + SH_ADD_HOOK(Test, Func2, pTest, SH_MEMBER(&hook, &CHook::Func2_Post1), true); + } +}; + +class TesterRefRetManual : public TesterRefRet +{ +public: + void AddHook__Test_Func1__Func1_Pre() + { + SH_ADD_MANUALHOOK(Manual_Test_Func1, pTest, SH_MEMBER(&hook, &CHook::Func1_Pre1), false); + } + + void AddHook__Test_Func1__Func1_Post() + { + SH_ADD_MANUALHOOK(Manual_Test_Func1, pTest, SH_MEMBER(&hook, &CHook::Func1_Post1), true); + } + + void AddHook__Test_Func1__Func1_Pre2() + { + SH_ADD_MANUALHOOK(Manual_Test_Func1, pTest, SH_MEMBER(&hook, &CHook::Func1_Pre2), false); + } + + void AddHook__Test_Func1__Func1_Post2() + { + SH_ADD_MANUALHOOK(Manual_Test_Func1, pTest, SH_MEMBER(&hook, &CHook::Func1_Post2), true); + } + + void AddHook__Test_Func2__Func2_Pre1() + { + SH_ADD_MANUALHOOK(Manual_Test_Func2, pTest, SH_MEMBER(&hook, &CHook::Func2_PreRecall_OverrideRet_Manual), false); + } + + void AddHook__Test_Func2__Func2_Post1() + { + SH_ADD_MANUALHOOK(Manual_Test_Func2, pTest, SH_MEMBER(&hook, &CHook::Func2_Post1), true); + } +}; + +bool TestRefRet(std::string &error) +{ + TesterRefRet *testerNonManual = new TesterRefRetNonManual; + bool resNonManual = testerNonManual->doTests(error); + if (!resNonManual) + { + return false; + } + + TesterRefRet *testerManual = new TesterRefRetManual; + bool resManual = testerManual->doTests(error); + if (!resManual) + { + return false; + } + return true; } diff --git a/sample_mm/Makefile b/sample_mm/Makefile index b932876..b277c0c 100644 --- a/sample_mm/Makefile +++ b/sample_mm/Makefile @@ -84,8 +84,8 @@ else endif endif -# if ENGINE is orig, OB, or L4D -ifneq (,$(filter original orangebox left4dead,$(ENGINE))) +# if ENGINE is original or OB +ifneq (,$(filter original orangebox,$(ENGINE))) LIB_SUFFIX = _i486.$(LIB_EXT) else LIB_PREFIX = lib diff --git a/stub_mm/Makefile b/stub_mm/Makefile index 8075fb6..0020247 100644 --- a/stub_mm/Makefile +++ b/stub_mm/Makefile @@ -84,8 +84,8 @@ else endif endif -# if ENGINE is orig, OB, or L4D -ifneq (,$(filter original orangebox left4dead,$(ENGINE))) +# if ENGINE is original or OB +ifneq (,$(filter original orangebox,$(ENGINE))) LIB_SUFFIX = _i486.$(LIB_EXT) else LIB_PREFIX = lib diff --git a/support/buildbot/package.pl b/support/buildbot/package.pl index 8751ff1..284c1cc 100755 --- a/support/buildbot/package.pl +++ b/support/buildbot/package.pl @@ -67,33 +67,25 @@ else my ($major,$minor) = ($version =~ /^(\d+)\.(\d+)/); $ftp_path .= "/$major.$minor"; -if ($^O eq "darwin") +my ($ftp); + +$ftp = Net::FTP->new($ftp_host, Debug => 0) + or die "Cannot connect to host $ftp_host: $@"; + +$ftp->login($ftp_user, $ftp_pass) + or die "Cannot connect to host $ftp_host as $ftp_user: " . $ftp->message . "\n"; + +if ($ftp_path ne '') { - # Horrible workaround for weird upload failure - system("ftp -Vu ftp://$ftp_user:$ftp_pass\@$ftp_host/$ftp_path/$filename $filename"); + $ftp->cwd($ftp_path) + or die "Cannot change to folder $ftp_path: " . $ftp->message . "\n"; } -else -{ - my ($ftp); - $ftp = Net::FTP->new($ftp_host, Debug => 0) - or die "Cannot connect to host $ftp_host: $@"; +$ftp->binary(); +$ftp->put($filename) + or die "Cannot drop file $filename ($ftp_path): " . $ftp->message . "\n"; - $ftp->login($ftp_user, $ftp_pass) - or die "Cannot connect to host $ftp_host as $ftp_user: " . $ftp->message . "\n"; - - if ($ftp_path ne '') - { - $ftp->cwd($ftp_path) - or die "Cannot change to folder $ftp_path: " . $ftp->message . "\n"; - } - - $ftp->binary(); - $ftp->put($filename) - or die "Cannot drop file $filename ($ftp_path): " . $ftp->message . "\n"; - - $ftp->close(); -} +$ftp->close(); print "File sent to drop site as $filename -- build succeeded.\n";