diff --git a/components/detours/Clean.bat b/components/detours/Clean.bat
new file mode 100644
index 00000000..a3f0c053
--- /dev/null
+++ b/components/detours/Clean.bat
@@ -0,0 +1,35 @@
+rem *****************************************
+rem * Delphi CleanUp Batch. *
+rem * *
+rem * Clean identcache,local,dcu,exe, *
+rem * map,drc files. *
+rem * Clean hidden __history folder. *
+rem * *
+rem * Author: Mahdi Safsafi *
+rem *****************************************
+
+@echo off
+Setlocal EnableDelayedExpansion
+
+Del "*.identcache" /s/q
+Del "*.local" /s/q
+Del "*.dcu" /s/q
+Del "*.exe" /s/q
+Del "*.drc" /s/q
+Del "*.map" /s/q
+
+set mustdel=false
+For /r %%f in (.) do (
+ set "mustdel=false"
+ if %%~nf==Win32 (
+ if exist "%%~ff\Debug\" set "mustdel=true"
+ if exist "%%~ff\Release\" set "mustdel=true"
+) else if %%~nf==Win64 (
+ if exist "%%~ff\Debug\" set "mustdel=true"
+ if exist "%%~ff\Release\" set "mustdel=true"
+ )
+if %%~nf==__history set "mustdel=true"
+if !mustdel!==true (
+ if exist "%%~ff" rd /s/q "%%~ff"
+ )
+)
\ No newline at end of file
diff --git a/components/detours/Demo/DetoursDemo/COM/Demo1/Demo1.dpr b/components/detours/Demo/DetoursDemo/COM/Demo1/Demo1.dpr
new file mode 100644
index 00000000..7b1c4b71
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/COM/Demo1/Demo1.dpr
@@ -0,0 +1,18 @@
+// JCL_DEBUG_EXPERT_GENERATEJDBG OFF
+program Demo1;
+
+uses
+ Vcl.Forms,
+ uMain in 'uMain.pas' {Main},
+ CPUID in '..\..\..\..\Source\CPUID.pas',
+ DDetours in '..\..\..\..\Source\DDetours.pas',
+ InstDecode in '..\..\..\..\Source\InstDecode.pas';
+
+{$R *.res}
+
+begin
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TMain, Main);
+ Application.Run;
+end.
diff --git a/components/detours/Demo/DetoursDemo/COM/Demo1/Demo1.dproj b/components/detours/Demo/DetoursDemo/COM/Demo1/Demo1.dproj
new file mode 100644
index 00000000..e57be60d
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/COM/Demo1/Demo1.dproj
@@ -0,0 +1,539 @@
+
+
+ {18E3F860-77E5-45A6-BF0A-445D77BE5AC5}
+ 18.1
+ VCL
+ Demo1.dpr
+ True
+ Debug
+ Win64
+ 3
+ Application
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ Demo1
+ .\$(Platform)\$(Config)
+ .\$(Platform)\$(Config)
+ false
+ false
+ false
+ false
+ false
+
+
+ true
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;CloudService;IndyIPCommon;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;svnui;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;vclactnband;FMXTee;soaprtl;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;emsclient;VCLRESTComponents;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;Intraweb;VclSmp;DataSnapConnectors;DataSnapServerMidas;DBXFirebirdDriver;dsnapcon;inet;fmxobj;FireDACMySQLDriver;soapmidas;vclx;svn;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;dbexpress;FireDACMSAccDriver;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage)
+ 1033
+ true
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
+ $(BDS)\bin\default_app.manifest
+
+
+ true
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
+ FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;CloudService;IndyIPCommon;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;vclactnband;FMXTee;soaprtl;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;emsclient;VCLRESTComponents;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;Intraweb;VclSmp;DataSnapConnectors;DataSnapServerMidas;DBXFirebirdDriver;dsnapcon;inet;fmxobj;FireDACMySQLDriver;soapmidas;vclx;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;dbexpress;FireDACMSAccDriver;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage)
+ 1033
+ true
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
+ $(BDS)\bin\default_app.manifest
+
+
+ DEBUG;$(DCC_Define)
+ true
+ false
+ true
+ true
+ true
+
+
+ false
+
+
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+
+ MainSource
+
+
+
+ dfm
+
+
+
+
+
+ Cfg_2
+ Base
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+
+ Delphi.Personality.12
+ Application
+
+
+
+ Demo1.dpr
+
+
+
+
+
+ Demo1.exe
+ true
+
+
+
+
+ Demo1.exe
+ true
+
+
+
+
+ Demo1.rsm
+ true
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ classes
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ Contents\MacOS
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+
+
+ library\lib\mips
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ 1
+
+
+
+
+ 0
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ library\lib\armeabi
+ 1
+
+
+
+
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ res\drawable-normal
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-large
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ Contents
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+
+
+ res\drawable-small
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+
+
+ 0
+
+
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 0
+ .bpl
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-xlarge
+ 1
+
+
+
+
+ res\drawable-ldpi
+ 1
+
+
+
+
+ 0
+ .dll;.bpl
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ 12
+
+
+
+
+
diff --git a/components/detours/Demo/DetoursDemo/COM/Demo1/Demo1.res b/components/detours/Demo/DetoursDemo/COM/Demo1/Demo1.res
new file mode 100644
index 00000000..0f3facb9
Binary files /dev/null and b/components/detours/Demo/DetoursDemo/COM/Demo1/Demo1.res differ
diff --git a/components/detours/Demo/DetoursDemo/COM/Demo1/uMain.dfm b/components/detours/Demo/DetoursDemo/COM/Demo1/uMain.dfm
new file mode 100644
index 00000000..f69a80af
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/COM/Demo1/uMain.dfm
@@ -0,0 +1,54 @@
+object Main: TMain
+ Left = 0
+ Top = 0
+ BorderStyle = bsSizeToolWin
+ Caption = 'Hooking IFileOpenDialog.Show Method'
+ ClientHeight = 196
+ ClientWidth = 447
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ OldCreateOrder = False
+ PixelsPerInch = 96
+ TextHeight = 13
+ object BtnOpenDialog: TButton
+ Left = 304
+ Top = 97
+ Width = 121
+ Height = 25
+ Caption = 'Open File Dialog'
+ TabOrder = 0
+ OnClick = BtnOpenDialogClick
+ end
+ object MemLog: TMemo
+ Left = 0
+ Top = 0
+ Width = 447
+ Height = 81
+ Align = alTop
+ Lines.Strings = (
+ 'MemLog')
+ TabOrder = 1
+ end
+ object BtnEnableHook: TButton
+ Left = 304
+ Top = 128
+ Width = 121
+ Height = 25
+ Caption = 'Enable Hook'
+ TabOrder = 2
+ OnClick = BtnEnableHookClick
+ end
+ object BtnDisableHook: TButton
+ Left = 304
+ Top = 159
+ Width = 121
+ Height = 25
+ Caption = 'Disable Hook'
+ TabOrder = 3
+ OnClick = BtnDisableHookClick
+ end
+end
diff --git a/components/detours/Demo/DetoursDemo/COM/Demo1/uMain.pas b/components/detours/Demo/DetoursDemo/COM/Demo1/uMain.pas
new file mode 100644
index 00000000..e440045e
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/COM/Demo1/uMain.pas
@@ -0,0 +1,78 @@
+unit uMain;
+
+interface
+
+uses
+ Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
+ Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, DDetours;
+
+type
+ TMain = class(TForm)
+ BtnOpenDialog: TButton;
+ MemLog: TMemo;
+ BtnEnableHook: TButton;
+ BtnDisableHook: TButton;
+ procedure BtnOpenDialogClick(Sender: TObject);
+ procedure BtnEnableHookClick(Sender: TObject);
+ procedure BtnDisableHookClick(Sender: TObject);
+ private
+ { Private declarations }
+ public
+ { Public declarations }
+ end;
+
+var
+ Main: TMain;
+
+implementation
+
+uses ShlObj, ComObj;
+{$R *.dfm}
+
+var
+ Trampoline_FileOpenDialog_Show: function(const Self; hwndParent: HWND): HRESULT; stdcall;
+ Trampoline_FileOpenDialog_SetTitle: function(const Self; pszTitle: LPCWSTR): HRESULT; stdcall;
+
+function FileOpenDialog_SetTitle_Hook(const Self; pszTitle: LPCWSTR): HRESULT; stdcall;
+begin
+ Result := Trampoline_FileOpenDialog_SetTitle(Self, 'Hooked');
+end;
+
+function FileOpenDialog_Show_Hook(const Self; hwndParent: HWND): HRESULT; stdcall;
+begin
+ Main.MemLog.Lines.Add('Execution FileOpenDialog.Show ..');
+ Result := Trampoline_FileOpenDialog_Show(Self, hwndParent);
+end;
+
+var
+ FileOpenDialog: IFileOpenDialog;
+
+procedure TMain.BtnOpenDialogClick(Sender: TObject);
+begin
+ MemLog.Clear;
+ FileOpenDialog.SetTitle('Open..');
+ FileOpenDialog.Show(Handle);
+end;
+
+procedure TMain.BtnEnableHookClick(Sender: TObject);
+begin
+ if not Assigned(Trampoline_FileOpenDialog_Show) then
+ @Trampoline_FileOpenDialog_Show := InterceptCreate(FileOpenDialog, 3, @FileOpenDialog_Show_Hook);
+ Trampoline_FileOpenDialog_SetTitle := InterceptCreate(FileOpenDialog, 17, @FileOpenDialog_SetTitle_Hook);
+end;
+
+procedure TMain.BtnDisableHookClick(Sender: TObject);
+begin
+ if Assigned(Trampoline_FileOpenDialog_Show) then
+ begin
+ InterceptRemove(@Trampoline_FileOpenDialog_Show);
+ Trampoline_FileOpenDialog_Show := nil;
+ end;
+ InterceptRemove(@Trampoline_FileOpenDialog_SetTitle)
+end;
+
+initialization
+
+FileOpenDialog := CreateComObject(CLSID_FileOpenDialog) as IFileOpenDialog;
+
+end.
diff --git a/components/detours/Demo/DetoursDemo/Delphi/Hook_Overloaded_Method/Hook_Overloaded_Method.dpr b/components/detours/Demo/DetoursDemo/Delphi/Hook_Overloaded_Method/Hook_Overloaded_Method.dpr
new file mode 100644
index 00000000..c47f7367
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/Delphi/Hook_Overloaded_Method/Hook_Overloaded_Method.dpr
@@ -0,0 +1,47 @@
+program Hook_Overloaded_Method;
+
+{$APPTYPE CONSOLE}
+{$R *.res}
+
+uses
+ System.SysUtils,
+ CPUID in '..\..\..\..\Source\CPUID.pas',
+ DDetours in '..\..\..\..\Source\DDetours.pas',
+ InstDecode in '..\..\..\..\Source\InstDecode.pas';
+
+type
+ TShowMsg = procedure(Value: Integer);
+
+var
+
+ TrampoShowMsg: TShowMsg;
+ { When hooking overloaded method ,
+ Delphi does not reconize the desired method .
+ So we need to use this trick!
+ }
+ MyMethodPtr: TShowMsg;
+
+procedure ShowMsg(const S: String); overload;
+begin
+ Writeln(S);
+end;
+
+procedure ShowMsg(Value: Integer); overload;
+begin
+ Writeln(Value);
+end;
+
+procedure ShowMsgHooked(Value: Integer);
+begin
+ Writeln('Method hooked successfully!');
+ TrampoShowMsg(Value + 1);
+end;
+
+begin
+ MyMethodPtr := ShowMsg;
+ @TrampoShowMsg := InterceptCreate(@MyMethodPtr, @ShowMsgHooked);
+ ShowMsg('Hi');
+ ShowMsg(2015);
+ ReadLn;
+
+end.
diff --git a/components/detours/Demo/DetoursDemo/Delphi/Hook_Overloaded_Method/Hook_Overloaded_Method.dproj b/components/detours/Demo/DetoursDemo/Delphi/Hook_Overloaded_Method/Hook_Overloaded_Method.dproj
new file mode 100644
index 00000000..553aa9bd
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/Delphi/Hook_Overloaded_Method/Hook_Overloaded_Method.dproj
@@ -0,0 +1,625 @@
+
+
+ {E9A76233-969C-4733-B759-3191ED9B483B}
+ 18.1
+ None
+ Hook_Overloaded_Method.dpr
+ True
+ Debug
+ Win32
+ 1
+ Console
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ $(BDS)\bin\delphi_PROJECTICNS.icns
+ Hook_Overloaded_Method
+ System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
+ .\$(Platform)\$(Config)
+ .\$(Platform)\$(Config)
+ false
+ false
+ false
+ false
+ false
+
+
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
+ true
+ true
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
+ true
+ true
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
+ true
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
+ true
+ true
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
+ true
+ true
+ true
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
+
+
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_80x80.png
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_60x60.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_76x76.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_40x40.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_768x1024.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_1024x768.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_152x152.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_2048x1536.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_1536x2048.png
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_40x40.png
+
+
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_80x80.png
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_60x60.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_76x76.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_40x40.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_768x1024.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_1024x768.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_152x152.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_2048x1536.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_1536x2048.png
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_40x40.png
+
+
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_80x80.png
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_60x60.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_76x76.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_40x40.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_768x1024.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_1024x768.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_152x152.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_2048x1536.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_1536x2048.png
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_40x40.png
+
+
+ FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;CloudService;IndyIPCommon;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;svnui;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;vclactnband;FMXTee;soaprtl;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;emsclient;VCLRESTComponents;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;Intraweb;VclSmp;DataSnapConnectors;DataSnapServerMidas;DBXFirebirdDriver;dsnapcon;inet;fmxobj;FireDACMySQLDriver;soapmidas;vclx;svn;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;dbexpress;FireDACMSAccDriver;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage)
+ true
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
+ 1033
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+
+
+ true
+ FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;CloudService;IndyIPCommon;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;vclactnband;FMXTee;soaprtl;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;emsclient;VCLRESTComponents;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;Intraweb;VclSmp;DataSnapConnectors;DataSnapServerMidas;DBXFirebirdDriver;dsnapcon;inet;fmxobj;FireDACMySQLDriver;soapmidas;vclx;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;dbexpress;FireDACMSAccDriver;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage)
+
+
+ DEBUG;$(DCC_Define)
+ true
+ false
+ true
+ true
+ true
+
+
+ false
+
+
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+
+ MainSource
+
+
+
+
+
+ Cfg_2
+ Base
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+
+ Delphi.Personality.12
+ Application
+
+
+
+ Hook_Overloaded_Method.dpr
+
+
+
+
+
+ Hook_Overloaded_Method.exe
+ true
+
+
+
+
+ true
+
+
+
+
+ true
+
+
+
+
+ true
+
+
+
+
+ true
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ classes
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ Contents\MacOS
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+
+
+ library\lib\mips
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ 1
+
+
+
+
+ 0
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ library\lib\armeabi
+ 1
+
+
+
+
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ res\drawable-normal
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-large
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ Contents
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+
+
+ res\drawable-small
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+
+
+ 0
+
+
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 0
+ .bpl
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-xlarge
+ 1
+
+
+
+
+ res\drawable-ldpi
+ 1
+
+
+
+
+ 0
+ .dll;.bpl
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+
+
+
+
+
+
+
+
+
+
+ False
+ False
+ False
+ False
+ False
+ True
+ False
+
+
+ 12
+
+
+
+
+
diff --git a/components/detours/Demo/DetoursDemo/Delphi/Interfaces/Demo1/Demo1.dpr b/components/detours/Demo/DetoursDemo/Delphi/Interfaces/Demo1/Demo1.dpr
new file mode 100644
index 00000000..6044c216
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/Delphi/Interfaces/Demo1/Demo1.dpr
@@ -0,0 +1,18 @@
+// JCL_DEBUG_EXPERT_GENERATEJDBG OFF
+program Demo1;
+
+uses
+ Vcl.Forms,
+ uMain in 'uMain.pas' {Main},
+ CPUID in '..\..\..\..\..\Source\CPUID.pas',
+ DDetours in '..\..\..\..\..\Source\DDetours.pas',
+ InstDecode in '..\..\..\..\..\Source\InstDecode.pas';
+
+{$R *.res}
+
+begin
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TMain, Main);
+ Application.Run;
+end.
diff --git a/components/detours/Demo/DetoursDemo/Delphi/Interfaces/Demo1/Demo1.dproj b/components/detours/Demo/DetoursDemo/Delphi/Interfaces/Demo1/Demo1.dproj
new file mode 100644
index 00000000..5fc7f47a
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/Delphi/Interfaces/Demo1/Demo1.dproj
@@ -0,0 +1,521 @@
+
+
+ {A523E817-0A23-4476-91C8-42FA45FF0F64}
+ 18.1
+ VCL
+ Demo1.dpr
+ True
+ Debug
+ Win32
+ 1
+ Application
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
+ Demo1
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ .\$(Platform)\$(Config)
+ .\$(Platform)\$(Config)
+ false
+ false
+ false
+ false
+ false
+
+
+ true
+ FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;CloudService;IndyIPCommon;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;svnui;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;vclactnband;FMXTee;soaprtl;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;emsclient;VCLRESTComponents;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;Intraweb;VclSmp;DataSnapConnectors;DataSnapServerMidas;DBXFirebirdDriver;dsnapcon;inet;fmxobj;FireDACMySQLDriver;soapmidas;vclx;svn;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;dbexpress;FireDACMSAccDriver;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage)
+ 1033
+ true
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
+ $(BDS)\bin\default_app.manifest
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+
+
+ FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;CloudService;IndyIPCommon;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;vclactnband;FMXTee;soaprtl;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;emsclient;VCLRESTComponents;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;Intraweb;VclSmp;DataSnapConnectors;DataSnapServerMidas;DBXFirebirdDriver;dsnapcon;inet;fmxobj;FireDACMySQLDriver;soapmidas;vclx;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;dbexpress;FireDACMSAccDriver;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage)
+
+
+ DEBUG;$(DCC_Define)
+ true
+ false
+ true
+ true
+ true
+
+
+ false
+
+
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+
+ MainSource
+
+
+
+ dfm
+
+
+
+
+
+ Cfg_2
+ Base
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+
+ Delphi.Personality.12
+ Application
+
+
+
+ Demo1.dpr
+
+
+
+
+
+ Demo1.exe
+ true
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ classes
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ Contents\MacOS
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+
+
+ library\lib\mips
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ 1
+
+
+
+
+ 0
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ library\lib\armeabi
+ 1
+
+
+
+
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ res\drawable-normal
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-large
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ Contents
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+
+
+ res\drawable-small
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+
+
+ 0
+
+
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 0
+ .bpl
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-xlarge
+ 1
+
+
+
+
+ res\drawable-ldpi
+ 1
+
+
+
+
+ 0
+ .dll;.bpl
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ False
+
+
+ 12
+
+
+
+
+
diff --git a/components/detours/Demo/DetoursDemo/Delphi/Interfaces/Demo1/uMain.dfm b/components/detours/Demo/DetoursDemo/Delphi/Interfaces/Demo1/uMain.dfm
new file mode 100644
index 00000000..f7ca056a
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/Delphi/Interfaces/Demo1/uMain.dfm
@@ -0,0 +1,44 @@
+object Main: TMain
+ Left = 0
+ Top = 0
+ BorderStyle = bsSizeToolWin
+ Caption = 'Hooking Method in interface'
+ ClientHeight = 133
+ ClientWidth = 298
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ OldCreateOrder = False
+ PixelsPerInch = 96
+ TextHeight = 13
+ object BtnCallShowMsg: TButton
+ Left = 32
+ Top = 24
+ Width = 241
+ Height = 25
+ Caption = 'Call ShowMsg'
+ TabOrder = 0
+ OnClick = BtnCallShowMsgClick
+ end
+ object BtnHook: TButton
+ Left = 32
+ Top = 55
+ Width = 241
+ Height = 25
+ Caption = 'Hook ShowMsg'
+ TabOrder = 1
+ OnClick = BtnHookClick
+ end
+ object BtnUnHook: TButton
+ Left = 32
+ Top = 86
+ Width = 241
+ Height = 25
+ Caption = 'UnHook ShowMsg '
+ TabOrder = 2
+ OnClick = BtnUnHookClick
+ end
+end
diff --git a/components/detours/Demo/DetoursDemo/Delphi/Interfaces/Demo1/uMain.pas b/components/detours/Demo/DetoursDemo/Delphi/Interfaces/Demo1/uMain.pas
new file mode 100644
index 00000000..a0b194a1
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/Delphi/Interfaces/Demo1/uMain.pas
@@ -0,0 +1,81 @@
+unit uMain;
+
+interface
+
+uses
+ Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
+ Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, DDetours;
+
+type
+ TMain = class(TForm)
+ BtnCallShowMsg: TButton;
+ BtnHook: TButton;
+ BtnUnHook: TButton;
+ procedure BtnCallShowMsgClick(Sender: TObject);
+ procedure BtnHookClick(Sender: TObject);
+ procedure BtnUnHookClick(Sender: TObject);
+ private
+ { Private declarations }
+ public
+ { Public declarations }
+ end;
+
+type
+ IMyInterface = Interface
+ procedure ShowMsg(const Msg: String);
+ End;
+
+ TMyObject = class(TInterfacedObject, IMyInterface)
+ public
+ procedure ShowMsg(const Msg: String);
+ end;
+
+var
+ Main: TMain;
+ FMyInterface: IMyInterface;
+
+implementation
+
+{$R *.dfm}
+
+var
+ TrampolineShowMsg: procedure(const Self; const Msg: String) = nil;
+
+procedure TMain.BtnUnHookClick(Sender: TObject);
+begin
+ if Assigned(TrampolineShowMsg) then
+ begin
+ InterceptRemove(@TrampolineShowMsg);
+ TrampolineShowMsg := nil;
+ end;
+end;
+
+procedure TMain.BtnCallShowMsgClick(Sender: TObject);
+begin
+ FMyInterface.ShowMsg('This is a test !');
+end;
+
+procedure InterceptShowMsg(const Self; const Msg: String);
+begin
+ TrampolineShowMsg(Self, 'Hooked');
+end;
+{ TMyObject }
+
+procedure TMyObject.ShowMsg(const Msg: String);
+var
+ S: String;
+begin
+ S := 'Your Message : ' + Msg;
+ ShowMessage(S);
+end;
+
+procedure TMain.BtnHookClick(Sender: TObject);
+begin
+ @TrampolineShowMsg := InterceptCreate(FMyInterface, 3, @InterceptShowMsg);
+end;
+
+initialization
+
+FMyInterface := TMyObject.Create;
+
+end.
diff --git a/components/detours/Demo/DetoursDemo/Delphi/Objects/Demo1/Demo1.dpr b/components/detours/Demo/DetoursDemo/Delphi/Objects/Demo1/Demo1.dpr
new file mode 100644
index 00000000..6044c216
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/Delphi/Objects/Demo1/Demo1.dpr
@@ -0,0 +1,18 @@
+// JCL_DEBUG_EXPERT_GENERATEJDBG OFF
+program Demo1;
+
+uses
+ Vcl.Forms,
+ uMain in 'uMain.pas' {Main},
+ CPUID in '..\..\..\..\..\Source\CPUID.pas',
+ DDetours in '..\..\..\..\..\Source\DDetours.pas',
+ InstDecode in '..\..\..\..\..\Source\InstDecode.pas';
+
+{$R *.res}
+
+begin
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TMain, Main);
+ Application.Run;
+end.
diff --git a/components/detours/Demo/DetoursDemo/Delphi/Objects/Demo1/Demo1.dproj b/components/detours/Demo/DetoursDemo/Delphi/Objects/Demo1/Demo1.dproj
new file mode 100644
index 00000000..7918447c
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/Delphi/Objects/Demo1/Demo1.dproj
@@ -0,0 +1,521 @@
+
+
+ {F786E6F9-BE54-4103-ADFF-11BC6C8629F0}
+ 18.1
+ VCL
+ Demo1.dpr
+ True
+ Debug
+ Win32
+ 1
+ Application
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
+ Demo1
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ .\$(Platform)\$(Config)
+ .\$(Platform)\$(Config)
+ false
+ false
+ false
+ false
+ false
+
+
+ true
+ FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;CloudService;IndyIPCommon;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;svnui;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;vclactnband;FMXTee;soaprtl;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;emsclient;VCLRESTComponents;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;Intraweb;VclSmp;DataSnapConnectors;DataSnapServerMidas;DBXFirebirdDriver;dsnapcon;inet;fmxobj;FireDACMySQLDriver;soapmidas;vclx;svn;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;dbexpress;FireDACMSAccDriver;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage)
+ 1033
+ true
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
+ $(BDS)\bin\default_app.manifest
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+
+
+ FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;CloudService;IndyIPCommon;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;vclactnband;FMXTee;soaprtl;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;emsclient;VCLRESTComponents;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;Intraweb;VclSmp;DataSnapConnectors;DataSnapServerMidas;DBXFirebirdDriver;dsnapcon;inet;fmxobj;FireDACMySQLDriver;soapmidas;vclx;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;dbexpress;FireDACMSAccDriver;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage)
+
+
+ DEBUG;$(DCC_Define)
+ true
+ false
+ true
+ true
+ true
+
+
+ false
+
+
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+
+ MainSource
+
+
+
+ dfm
+
+
+
+
+
+ Cfg_2
+ Base
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+
+ Delphi.Personality.12
+ Application
+
+
+
+ Demo1.dpr
+
+
+
+
+
+ Demo1.exe
+ true
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ classes
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ Contents\MacOS
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+
+
+ library\lib\mips
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ 1
+
+
+
+
+ 0
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ library\lib\armeabi
+ 1
+
+
+
+
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ res\drawable-normal
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-large
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ Contents
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+
+
+ res\drawable-small
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+
+
+ 0
+
+
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 0
+ .bpl
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-xlarge
+ 1
+
+
+
+
+ res\drawable-ldpi
+ 1
+
+
+
+
+ 0
+ .dll;.bpl
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ False
+
+
+ 12
+
+
+
+
+
diff --git a/components/detours/Demo/DetoursDemo/Delphi/Objects/Demo1/uMain.dfm b/components/detours/Demo/DetoursDemo/Delphi/Objects/Demo1/uMain.dfm
new file mode 100644
index 00000000..9702c526
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/Delphi/Objects/Demo1/uMain.dfm
@@ -0,0 +1,52 @@
+object Main: TMain
+ Left = 0
+ Top = 0
+ BorderStyle = bsSizeToolWin
+ Caption = 'Hooking TControl.SetTextBuf'
+ ClientHeight = 164
+ ClientWidth = 178
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ OldCreateOrder = False
+ PixelsPerInch = 96
+ TextHeight = 13
+ object BtnEnableHook: TButton
+ Left = 17
+ Top = 90
+ Width = 151
+ Height = 25
+ Caption = 'BtnEnableHook'
+ TabOrder = 0
+ OnClick = BtnEnableHookClick
+ end
+ object BtnDisableHook: TButton
+ Left = 17
+ Top = 116
+ Width = 151
+ Height = 25
+ Caption = 'BtnDisableHook'
+ TabOrder = 1
+ OnClick = BtnDisableHookClick
+ end
+ object Edit1: TEdit
+ Left = 17
+ Top = 24
+ Width = 151
+ Height = 21
+ TabOrder = 2
+ Text = 'Hi'
+ end
+ object BtnClickMe: TButton
+ Left = 17
+ Top = 51
+ Width = 151
+ Height = 25
+ Caption = 'Click Me'
+ TabOrder = 3
+ OnClick = BtnClickMeClick
+ end
+end
diff --git a/components/detours/Demo/DetoursDemo/Delphi/Objects/Demo1/uMain.pas b/components/detours/Demo/DetoursDemo/Delphi/Objects/Demo1/uMain.pas
new file mode 100644
index 00000000..2de10be7
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/Delphi/Objects/Demo1/uMain.pas
@@ -0,0 +1,62 @@
+unit uMain;
+
+interface
+
+uses
+ Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
+ Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, DDetours;
+
+type
+ TMain = class(TForm)
+ BtnEnableHook: TButton;
+ BtnDisableHook: TButton;
+ Edit1: TEdit;
+ BtnClickMe: TButton;
+ procedure BtnEnableHookClick(Sender: TObject);
+ procedure BtnDisableHookClick(Sender: TObject);
+ procedure BtnClickMeClick(Sender: TObject);
+ private
+ { Private declarations }
+ public
+ { Public declarations }
+ end;
+
+var
+ Main: TMain;
+
+implementation
+
+{$R *.dfm}
+
+var
+ TrampolineSetTextBuf: procedure(const Self; Buffer: PChar) = nil;
+
+procedure SetTextBufHooked(const Self; Buffer: PChar);
+var
+ S: String;
+begin
+ S := 'Hooked _' + String(Buffer);
+ TrampolineSetTextBuf(Self, PChar(S)); // Call the original function .
+end;
+
+procedure TMain.BtnDisableHookClick(Sender: TObject);
+begin
+ if Assigned(TrampolineSetTextBuf) then
+ begin
+ InterceptRemove(@TrampolineSetTextBuf);
+ TrampolineSetTextBuf := nil;
+ end;
+end;
+
+procedure TMain.BtnEnableHookClick(Sender: TObject);
+begin
+ Edit1.Text := 'Enter new text ..';
+ @TrampolineSetTextBuf := InterceptCreate(@TControl.SetTextBuf, @SetTextBufHooked);
+end;
+
+procedure TMain.BtnClickMeClick(Sender: TObject);
+begin
+ BtnClickMe.Caption := Edit1.Text;
+end;
+
+end.
diff --git a/components/detours/Demo/DetoursDemo/Delphi/RTL/Demo1/Demo1.dpr b/components/detours/Demo/DetoursDemo/Delphi/RTL/Demo1/Demo1.dpr
new file mode 100644
index 00000000..6044c216
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/Delphi/RTL/Demo1/Demo1.dpr
@@ -0,0 +1,18 @@
+// JCL_DEBUG_EXPERT_GENERATEJDBG OFF
+program Demo1;
+
+uses
+ Vcl.Forms,
+ uMain in 'uMain.pas' {Main},
+ CPUID in '..\..\..\..\..\Source\CPUID.pas',
+ DDetours in '..\..\..\..\..\Source\DDetours.pas',
+ InstDecode in '..\..\..\..\..\Source\InstDecode.pas';
+
+{$R *.res}
+
+begin
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TMain, Main);
+ Application.Run;
+end.
diff --git a/components/detours/Demo/DetoursDemo/Delphi/RTL/Demo1/Demo1.dproj b/components/detours/Demo/DetoursDemo/Delphi/RTL/Demo1/Demo1.dproj
new file mode 100644
index 00000000..cf66ecf8
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/Delphi/RTL/Demo1/Demo1.dproj
@@ -0,0 +1,539 @@
+
+
+ {FF06FC93-1560-45CE-9FF3-14F0C95618F4}
+ 18.1
+ VCL
+ Demo1.dpr
+ True
+ Debug
+ Win64
+ 3
+ Application
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ Demo1
+ .\$(Platform)\$(Config)
+ .\$(Platform)\$(Config)
+ false
+ false
+ false
+ false
+ false
+
+
+ true
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;CloudService;IndyIPCommon;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;svnui;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;vclactnband;FMXTee;soaprtl;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;emsclient;VCLRESTComponents;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;Intraweb;VclSmp;DataSnapConnectors;DataSnapServerMidas;DBXFirebirdDriver;dsnapcon;inet;fmxobj;FireDACMySQLDriver;soapmidas;vclx;svn;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;dbexpress;FireDACMSAccDriver;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage)
+ 1033
+ true
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
+ $(BDS)\bin\default_app.manifest
+
+
+ true
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
+ FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;CloudService;IndyIPCommon;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;vclactnband;FMXTee;soaprtl;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;emsclient;VCLRESTComponents;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;Intraweb;VclSmp;DataSnapConnectors;DataSnapServerMidas;DBXFirebirdDriver;dsnapcon;inet;fmxobj;FireDACMySQLDriver;soapmidas;vclx;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;dbexpress;FireDACMSAccDriver;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage)
+ 1033
+ true
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
+ $(BDS)\bin\default_app.manifest
+
+
+ DEBUG;$(DCC_Define)
+ true
+ false
+ true
+ true
+ true
+
+
+ false
+
+
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+
+ MainSource
+
+
+
+ dfm
+
+
+
+
+
+ Cfg_2
+ Base
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+
+ Delphi.Personality.12
+ Application
+
+
+
+ Demo1.dpr
+
+
+
+
+
+ Demo1.exe
+ true
+
+
+
+
+ Demo1.exe
+ true
+
+
+
+
+ Demo1.rsm
+ true
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ classes
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ Contents\MacOS
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+
+
+ library\lib\mips
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ 1
+
+
+
+
+ 0
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ library\lib\armeabi
+ 1
+
+
+
+
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ res\drawable-normal
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-large
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ Contents
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+
+
+ res\drawable-small
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+
+
+ 0
+
+
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 0
+ .bpl
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-xlarge
+ 1
+
+
+
+
+ res\drawable-ldpi
+ 1
+
+
+
+
+ 0
+ .dll;.bpl
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ 12
+
+
+
+
+
diff --git a/components/detours/Demo/DetoursDemo/Delphi/RTL/Demo1/Demo1.res b/components/detours/Demo/DetoursDemo/Delphi/RTL/Demo1/Demo1.res
new file mode 100644
index 00000000..0f3facb9
Binary files /dev/null and b/components/detours/Demo/DetoursDemo/Delphi/RTL/Demo1/Demo1.res differ
diff --git a/components/detours/Demo/DetoursDemo/Delphi/RTL/Demo1/uMain.dfm b/components/detours/Demo/DetoursDemo/Delphi/RTL/Demo1/uMain.dfm
new file mode 100644
index 00000000..eb63a5c5
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/Delphi/RTL/Demo1/uMain.dfm
@@ -0,0 +1,38 @@
+object Main: TMain
+ Left = 0
+ Top = 0
+ BorderStyle = bsSizeToolWin
+ Caption = 'Hooking GetMemory'
+ ClientHeight = 167
+ ClientWidth = 447
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ OldCreateOrder = False
+ OnCreate = FormCreate
+ PixelsPerInch = 96
+ TextHeight = 13
+ object MemLog: TMemo
+ Left = 0
+ Top = 0
+ Width = 447
+ Height = 113
+ Align = alTop
+ Lines.Strings = (
+ 'MemLog')
+ ScrollBars = ssVertical
+ TabOrder = 0
+ end
+ object BtnTest: TButton
+ Left = 302
+ Top = 136
+ Width = 137
+ Height = 25
+ Caption = 'Test'
+ TabOrder = 1
+ OnClick = BtnTestClick
+ end
+end
diff --git a/components/detours/Demo/DetoursDemo/Delphi/RTL/Demo1/uMain.pas b/components/detours/Demo/DetoursDemo/Delphi/RTL/Demo1/uMain.pas
new file mode 100644
index 00000000..d64d766d
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/Delphi/RTL/Demo1/uMain.pas
@@ -0,0 +1,93 @@
+unit uMain;
+
+interface
+
+uses
+ Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
+ Vcl.Controls, Vcl.Forms, Vcl.Dialogs, DDetours, Vcl.StdCtrls;
+
+type
+ TMyForm = class(TForm)
+ private
+ class var FInit: Boolean;
+ class constructor Create;
+ end;
+
+ TMain = class(TMyForm)
+ MemLog: TMemo;
+ BtnTest: TButton;
+ procedure FormCreate(Sender: TObject);
+ procedure BtnTestClick(Sender: TObject);
+ private
+
+ { Private declarations }
+ public
+ { Public declarations }
+ end;
+
+var
+ Main: TMain;
+
+implementation
+
+{$R *.dfm}
+
+var
+ TrampolineGetMemory: function(Size: NativeInt): Pointer;
+cdecl = nil;
+
+var
+ TrampolineFreeMemory: function(P: Pointer): Integer;
+cdecl = nil;
+
+function GetMemory_Hooked(Size: NativeInt): Pointer; cdecl;
+begin
+ Result := TrampolineGetMemory(Size);
+ if Main.FInit then
+ begin
+ Main.MemLog.Lines.Add(Format('Allocating %d bytes at %p.', [Size, Result]));
+ end;
+end;
+
+function FreeMemory_Hooked(P: Pointer): Integer; cdecl;
+begin
+ Result := TrampolineFreeMemory(P);
+ if Main.FInit then
+ begin
+ Main.MemLog.Lines.Add(Format('Freeing %p address.', [P]));
+ end;
+end;
+
+procedure TMain.BtnTestClick(Sender: TObject);
+var
+ P: PByte;
+begin
+ P := GetMemory(16);
+ FreeMemory(P);
+ MemLog.Lines.Add('---------------------------------');
+end;
+
+procedure TMain.FormCreate(Sender: TObject);
+begin
+ FInit := True;
+ MemLog.Clear;
+end;
+
+{ TMyForm }
+
+class constructor TMyForm.Create;
+begin
+ FInit := False;
+end;
+
+initialization
+
+@TrampolineGetMemory := InterceptCreate(@GetMemory, @GetMemory_Hooked);
+@TrampolineFreeMemory := InterceptCreate(@FreeMemory, @FreeMemory_Hooked);
+
+finalization
+
+InterceptRemove(@TrampolineGetMemory);
+InterceptRemove(@TrampolineFreeMemory);
+
+end.
diff --git a/components/detours/Demo/DetoursDemo/MultiHook/Demo1/Demo1.dpr b/components/detours/Demo/DetoursDemo/MultiHook/Demo1/Demo1.dpr
new file mode 100644
index 00000000..7c8ff19d
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/MultiHook/Demo1/Demo1.dpr
@@ -0,0 +1,17 @@
+program Demo1;
+
+uses
+ Vcl.Forms,
+ uMain in 'uMain.pas' {Main},
+ CPUID in '..\..\..\..\Source\CPUID.pas',
+ DDetours in '..\..\..\..\Source\DDetours.pas',
+ InstDecode in '..\..\..\..\Source\InstDecode.pas';
+
+{$R *.res}
+
+begin
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TMain, Main);
+ Application.Run;
+end.
diff --git a/components/detours/Demo/DetoursDemo/MultiHook/Demo1/Demo1.dproj b/components/detours/Demo/DetoursDemo/MultiHook/Demo1/Demo1.dproj
new file mode 100644
index 00000000..c1bd242b
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/MultiHook/Demo1/Demo1.dproj
@@ -0,0 +1,521 @@
+
+
+ {8D1CE223-B40B-479A-9234-47F5A8CD29FD}
+ 18.1
+ VCL
+ Demo1.dpr
+ True
+ Debug
+ Win32
+ 1
+ Application
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ Demo1
+ .\$(Platform)\$(Config)
+ .\$(Platform)\$(Config)
+ false
+ false
+ false
+ false
+ false
+
+
+ true
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;CloudService;IndyIPCommon;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;svnui;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;vclactnband;FMXTee;soaprtl;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;emsclient;VCLRESTComponents;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;Intraweb;VclSmp;DataSnapConnectors;DataSnapServerMidas;DBXFirebirdDriver;dsnapcon;inet;fmxobj;FireDACMySQLDriver;soapmidas;vclx;svn;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;dbexpress;FireDACMSAccDriver;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage)
+ 1033
+ true
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
+ $(BDS)\bin\default_app.manifest
+
+
+ FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;CloudService;IndyIPCommon;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;vclactnband;FMXTee;soaprtl;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;emsclient;VCLRESTComponents;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;Intraweb;VclSmp;DataSnapConnectors;DataSnapServerMidas;DBXFirebirdDriver;dsnapcon;inet;fmxobj;FireDACMySQLDriver;soapmidas;vclx;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;dbexpress;FireDACMSAccDriver;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage)
+
+
+ DEBUG;$(DCC_Define)
+ true
+ false
+ true
+ true
+ true
+
+
+ false
+
+
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+
+ MainSource
+
+
+
+ dfm
+
+
+
+
+
+ Cfg_2
+ Base
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+
+ Delphi.Personality.12
+ Application
+
+
+
+ Demo1.dpr
+
+
+
+
+
+ Demo1.exe
+ true
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ classes
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ Contents\MacOS
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+
+
+ library\lib\mips
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ 1
+
+
+
+
+ 0
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ library\lib\armeabi
+ 1
+
+
+
+
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ res\drawable-normal
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-large
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ Contents
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+
+
+ res\drawable-small
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+
+
+ 0
+
+
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 0
+ .bpl
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-xlarge
+ 1
+
+
+
+
+ res\drawable-ldpi
+ 1
+
+
+
+
+ 0
+ .dll;.bpl
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ False
+
+
+ 12
+
+
+
+
+
diff --git a/components/detours/Demo/DetoursDemo/MultiHook/Demo1/uMain.dfm b/components/detours/Demo/DetoursDemo/MultiHook/Demo1/uMain.dfm
new file mode 100644
index 00000000..06b7b7b8
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/MultiHook/Demo1/uMain.dfm
@@ -0,0 +1,91 @@
+object Main: TMain
+ Left = 0
+ Top = 0
+ Caption = 'Main'
+ ClientHeight = 264
+ ClientWidth = 447
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ OldCreateOrder = False
+ OnCreate = FormCreate
+ PixelsPerInch = 96
+ TextHeight = 13
+ object MemLog: TMemo
+ Left = 0
+ Top = 0
+ Width = 447
+ Height = 89
+ Align = alTop
+ Lines.Strings = (
+ 'MemLog')
+ ScrollBars = ssVertical
+ TabOrder = 0
+ end
+ object BtnEnableHook1: TButton
+ Left = 292
+ Top = 120
+ Width = 147
+ Height = 25
+ Caption = 'Enable Hook1'
+ TabOrder = 1
+ OnClick = BtnEnableHook1Click
+ end
+ object BtnEnableHook2: TButton
+ Left = 292
+ Top = 151
+ Width = 147
+ Height = 25
+ Caption = 'Enable Hook2'
+ TabOrder = 2
+ OnClick = BtnEnableHook2Click
+ end
+ object BtnEnableHook3: TButton
+ Left = 292
+ Top = 182
+ Width = 147
+ Height = 25
+ Caption = 'Enable Hook3'
+ TabOrder = 3
+ OnClick = BtnEnableHook3Click
+ end
+ object BtnRemoveHook1: TButton
+ Left = 28
+ Top = 120
+ Width = 147
+ Height = 25
+ Caption = 'Remove Hook1'
+ TabOrder = 4
+ OnClick = BtnRemoveHook1Click
+ end
+ object BtnRemoveHook2: TButton
+ Left = 28
+ Top = 151
+ Width = 147
+ Height = 25
+ Caption = 'Remove Hook2'
+ TabOrder = 5
+ OnClick = BtnRemoveHook2Click
+ end
+ object BtnRemoveHook3: TButton
+ Left = 28
+ Top = 182
+ Width = 147
+ Height = 25
+ Caption = 'Remove Hook3'
+ TabOrder = 6
+ OnClick = BtnRemoveHook3Click
+ end
+ object BtnTest: TButton
+ Left = 292
+ Top = 231
+ Width = 147
+ Height = 25
+ Caption = 'Test'
+ TabOrder = 7
+ OnClick = BtnTestClick
+ end
+end
diff --git a/components/detours/Demo/DetoursDemo/MultiHook/Demo1/uMain.pas b/components/detours/Demo/DetoursDemo/MultiHook/Demo1/uMain.pas
new file mode 100644
index 00000000..b21a3c7d
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/MultiHook/Demo1/uMain.pas
@@ -0,0 +1,122 @@
+unit uMain;
+
+interface
+
+uses
+ Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
+ Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, DDetours;
+
+type
+ TMain = class(TForm)
+ MemLog: TMemo;
+ BtnEnableHook1: TButton;
+ BtnEnableHook2: TButton;
+ BtnEnableHook3: TButton;
+ BtnRemoveHook1: TButton;
+ BtnRemoveHook2: TButton;
+ BtnRemoveHook3: TButton;
+ BtnTest: TButton;
+ procedure BtnEnableHook1Click(Sender: TObject);
+ procedure BtnEnableHook2Click(Sender: TObject);
+ procedure BtnEnableHook3Click(Sender: TObject);
+ procedure BtnRemoveHook1Click(Sender: TObject);
+ procedure BtnRemoveHook2Click(Sender: TObject);
+ procedure BtnRemoveHook3Click(Sender: TObject);
+ procedure BtnTestClick(Sender: TObject);
+ procedure FormCreate(Sender: TObject);
+ private
+ { Private declarations }
+ public
+ { Public declarations }
+ end;
+
+var
+ Main: TMain;
+
+implementation
+
+{$R *.dfm}
+
+type
+ TMsgBoxNextHookProc = function(hWnd: hWnd; lpText, lpCaption: LPCWSTR; uType: UINT): Integer; stdcall;
+
+var
+ NextHook1: TMsgBoxNextHookProc = nil;
+ NextHook2: TMsgBoxNextHookProc = nil;
+ NextHook3: TMsgBoxNextHookProc = nil;
+
+function MessageBox_Hook1(hWnd: hWnd; lpText, lpCaption: LPCWSTR; uType: UINT): Integer; stdcall;
+begin
+ Main.MemLog.Lines.Add('Hook 1 executed successfully.');
+ Result := NextHook1(hWnd, 'Hook1', lpCaption, uType);
+end;
+
+function MessageBox_Hook2(hWnd: hWnd; lpText, lpCaption: LPCWSTR; uType: UINT): Integer; stdcall;
+begin
+ Main.MemLog.Lines.Add('Hook 2 executed successfully.');
+ Result := NextHook2(hWnd, lpText, 'Hook2', uType);
+end;
+
+function MessageBox_Hook3(hWnd: hWnd; lpText, lpCaption: LPCWSTR; uType: UINT): Integer; stdcall;
+begin
+ Main.MemLog.Lines.Add('Hook 3 executed successfully.');
+ Result := NextHook3(hWnd, lpText, lpText, uType);
+end;
+
+procedure TMain.BtnEnableHook1Click(Sender: TObject);
+begin
+ if not Assigned(NextHook1) then
+ @NextHook1 := InterceptCreate(@MessageBox, @MessageBox_Hook1);
+end;
+
+procedure TMain.BtnEnableHook2Click(Sender: TObject);
+begin
+ if not Assigned(NextHook2) then
+ @NextHook2 := InterceptCreate(@MessageBox, @MessageBox_Hook2);
+end;
+
+procedure TMain.BtnEnableHook3Click(Sender: TObject);
+begin
+ if not Assigned(NextHook3) then
+ @NextHook3 := InterceptCreate(@MessageBox, @MessageBox_Hook3);
+end;
+
+procedure TMain.BtnRemoveHook1Click(Sender: TObject);
+begin
+ if Assigned(NextHook1) then
+ begin
+ InterceptRemove(@NextHook1);
+ NextHook1 := nil;
+ end;
+end;
+
+procedure TMain.BtnRemoveHook2Click(Sender: TObject);
+begin
+ if Assigned(NextHook2) then
+ begin
+ InterceptRemove(@NextHook2);
+ NextHook2 := nil;
+ end;
+end;
+
+procedure TMain.BtnRemoveHook3Click(Sender: TObject);
+begin
+ if Assigned(NextHook3) then
+ begin
+ InterceptRemove(@NextHook3);
+ NextHook3 := nil;
+ end;
+end;
+
+procedure TMain.BtnTestClick(Sender: TObject);
+begin
+ MemLog.Lines.Add('----------------------------');
+ MessageBox(Handle, 'Msg Text', 'Msg Caption', MB_OK);
+end;
+
+procedure TMain.FormCreate(Sender: TObject);
+begin
+ MemLog.Clear;
+end;
+
+end.
diff --git a/components/detours/Demo/DetoursDemo/win32api/Demo1/Demo1.dpr b/components/detours/Demo/DetoursDemo/win32api/Demo1/Demo1.dpr
new file mode 100644
index 00000000..7c8ff19d
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/win32api/Demo1/Demo1.dpr
@@ -0,0 +1,17 @@
+program Demo1;
+
+uses
+ Vcl.Forms,
+ uMain in 'uMain.pas' {Main},
+ CPUID in '..\..\..\..\Source\CPUID.pas',
+ DDetours in '..\..\..\..\Source\DDetours.pas',
+ InstDecode in '..\..\..\..\Source\InstDecode.pas';
+
+{$R *.res}
+
+begin
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TMain, Main);
+ Application.Run;
+end.
diff --git a/components/detours/Demo/DetoursDemo/win32api/Demo1/Demo1.dproj b/components/detours/Demo/DetoursDemo/win32api/Demo1/Demo1.dproj
new file mode 100644
index 00000000..913d98cc
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/win32api/Demo1/Demo1.dproj
@@ -0,0 +1,521 @@
+
+
+ {94A98E21-0A68-459A-87DB-F12416300062}
+ 18.1
+ VCL
+ Demo1.dpr
+ True
+ Debug
+ Win32
+ 1
+ Application
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ Demo1
+ .\$(Platform)\$(Config)
+ .\$(Platform)\$(Config)
+ false
+ false
+ false
+ false
+ false
+
+
+ true
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;CloudService;IndyIPCommon;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;svnui;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;vclactnband;FMXTee;soaprtl;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;emsclient;VCLRESTComponents;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;Intraweb;VclSmp;DataSnapConnectors;DataSnapServerMidas;DBXFirebirdDriver;dsnapcon;inet;fmxobj;FireDACMySQLDriver;soapmidas;vclx;svn;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;dbexpress;FireDACMSAccDriver;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage)
+ 1033
+ true
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
+ $(BDS)\bin\default_app.manifest
+
+
+ FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;CloudService;IndyIPCommon;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;vclactnband;FMXTee;soaprtl;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;emsclient;VCLRESTComponents;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;Intraweb;VclSmp;DataSnapConnectors;DataSnapServerMidas;DBXFirebirdDriver;dsnapcon;inet;fmxobj;FireDACMySQLDriver;soapmidas;vclx;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;dbexpress;FireDACMSAccDriver;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage)
+
+
+ DEBUG;$(DCC_Define)
+ true
+ false
+ true
+ true
+ true
+
+
+ false
+
+
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+
+ MainSource
+
+
+
+ dfm
+
+
+
+
+
+ Cfg_2
+ Base
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+
+ Delphi.Personality.12
+ Application
+
+
+
+ Demo1.dpr
+
+
+
+
+
+ Demo1.exe
+ true
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ classes
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ Contents\MacOS
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+
+
+ library\lib\mips
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ 1
+
+
+
+
+ 0
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ library\lib\armeabi
+ 1
+
+
+
+
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ res\drawable-normal
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-large
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ Contents
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+
+
+ res\drawable-small
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+
+
+ 0
+
+
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 0
+ .bpl
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-xlarge
+ 1
+
+
+
+
+ res\drawable-ldpi
+ 1
+
+
+
+
+ 0
+ .dll;.bpl
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ False
+
+
+ 12
+
+
+
+
+
diff --git a/components/detours/Demo/DetoursDemo/win32api/Demo1/uMain.dfm b/components/detours/Demo/DetoursDemo/win32api/Demo1/uMain.dfm
new file mode 100644
index 00000000..87fb2f8b
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/win32api/Demo1/uMain.dfm
@@ -0,0 +1,44 @@
+object Main: TMain
+ Left = 0
+ Top = 0
+ BorderStyle = bsSizeToolWin
+ Caption = 'Hooking MessageBox'
+ ClientHeight = 133
+ ClientWidth = 188
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ OldCreateOrder = False
+ PixelsPerInch = 96
+ TextHeight = 13
+ object BtnHook: TButton
+ Left = 16
+ Top = 24
+ Width = 153
+ Height = 25
+ Caption = 'Hook MessageBox'
+ TabOrder = 0
+ OnClick = BtnHookClick
+ end
+ object BtnUnHook: TButton
+ Left = 16
+ Top = 88
+ Width = 153
+ Height = 25
+ Caption = 'UnHook MessageBox'
+ TabOrder = 1
+ OnClick = BtnUnHookClick
+ end
+ object BtnTestMsgBox: TButton
+ Left = 16
+ Top = 57
+ Width = 153
+ Height = 25
+ Caption = 'Call MessageBox'
+ TabOrder = 2
+ OnClick = BtnTestMsgBoxClick
+ end
+end
diff --git a/components/detours/Demo/DetoursDemo/win32api/Demo1/uMain.pas b/components/detours/Demo/DetoursDemo/win32api/Demo1/uMain.pas
new file mode 100644
index 00000000..afe843af
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/win32api/Demo1/uMain.pas
@@ -0,0 +1,61 @@
+unit uMain;
+
+interface
+
+uses
+ Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
+ Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, DDetours;
+
+type
+ TMain = class(TForm)
+ BtnHook: TButton;
+ BtnUnHook: TButton;
+ BtnTestMsgBox: TButton;
+ procedure BtnHookClick(Sender: TObject);
+ procedure BtnUnHookClick(Sender: TObject);
+ procedure BtnTestMsgBoxClick(Sender: TObject);
+ private
+ { Private declarations }
+ public
+ { Public declarations }
+ end;
+
+var
+ Main: TMain;
+
+implementation
+
+{$R *.dfm}
+
+var
+ TrampolineMessageBoxW: function(hWnd: hWnd; lpText, lpCaption: LPCWSTR; uType: UINT): Integer;
+stdcall = nil;
+
+function InterceptMessageBoxW(hWnd: hWnd; lpText, lpCaption: LPCWSTR; uType: UINT): Integer; stdcall;
+begin
+ Result := TrampolineMessageBoxW(hWnd, 'Hooked', 'Hooked', MB_OK or MB_ICONEXCLAMATION);
+end;
+
+procedure TMain.BtnHookClick(Sender: TObject);
+begin
+ if not Assigned(TrampolineMessageBoxW) then
+ begin
+ @TrampolineMessageBoxW := InterceptCreate(@MessageBoxW, @InterceptMessageBoxW);
+ end;
+end;
+
+procedure TMain.BtnTestMsgBoxClick(Sender: TObject);
+begin
+ MessageBoxW(Handle, 'Text', 'Caption', MB_OK);
+end;
+
+procedure TMain.BtnUnHookClick(Sender: TObject);
+begin
+ if Assigned(TrampolineMessageBoxW) then
+ begin
+ InterceptRemove(@TrampolineMessageBoxW);
+ TrampolineMessageBoxW := nil;
+ end;
+end;
+
+end.
diff --git a/components/detours/Demo/DetoursDemo/win32api/Demo2/Demo2.dpr b/components/detours/Demo/DetoursDemo/win32api/Demo2/Demo2.dpr
new file mode 100644
index 00000000..057f914c
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/win32api/Demo2/Demo2.dpr
@@ -0,0 +1,18 @@
+// JCL_DEBUG_EXPERT_GENERATEJDBG OFF
+program Demo2;
+
+uses
+ Vcl.Forms,
+ uMain in 'uMain.pas' {Main},
+ CPUID in '..\..\..\..\Source\CPUID.pas',
+ DDetours in '..\..\..\..\Source\DDetours.pas',
+ InstDecode in '..\..\..\..\Source\InstDecode.pas';
+
+{$R *.res}
+
+begin
+ Application.Initialize;
+ Application.MainFormOnTaskbar := True;
+ Application.CreateForm(TMain, Main);
+ Application.Run;
+end.
diff --git a/components/detours/Demo/DetoursDemo/win32api/Demo2/Demo2.dproj b/components/detours/Demo/DetoursDemo/win32api/Demo2/Demo2.dproj
new file mode 100644
index 00000000..ada8d102
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/win32api/Demo2/Demo2.dproj
@@ -0,0 +1,521 @@
+
+
+ {D20E30CF-BD39-428A-9E72-F6745BF708E6}
+ 18.1
+ VCL
+ Demo2.dpr
+ True
+ Debug
+ Win32
+ 1
+ Application
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)
+ Demo2
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ .\$(Platform)\$(Config)
+ .\$(Platform)\$(Config)
+ false
+ false
+ false
+ false
+ false
+
+
+ true
+ FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;CloudService;IndyIPCommon;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;svnui;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;vclactnband;FMXTee;soaprtl;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;emsclient;VCLRESTComponents;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;Intraweb;VclSmp;DataSnapConnectors;DataSnapServerMidas;DBXFirebirdDriver;dsnapcon;inet;fmxobj;FireDACMySQLDriver;soapmidas;vclx;svn;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;dbexpress;FireDACMSAccDriver;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage)
+ 1033
+ true
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
+ $(BDS)\bin\default_app.manifest
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+
+
+ FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;CloudService;IndyIPCommon;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;vclactnband;FMXTee;soaprtl;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;emsclient;VCLRESTComponents;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;Intraweb;VclSmp;DataSnapConnectors;DataSnapServerMidas;DBXFirebirdDriver;dsnapcon;inet;fmxobj;FireDACMySQLDriver;soapmidas;vclx;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;dbexpress;FireDACMSAccDriver;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage)
+
+
+ DEBUG;$(DCC_Define)
+ true
+ false
+ true
+ true
+ true
+
+
+ false
+
+
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+
+ MainSource
+
+
+
+ dfm
+
+
+
+
+
+ Cfg_2
+ Base
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+
+ Delphi.Personality.12
+ Application
+
+
+
+ Demo2.dpr
+
+
+
+
+
+ Demo2.exe
+ true
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ classes
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ Contents\MacOS
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+
+
+ library\lib\mips
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ 1
+
+
+
+
+ 0
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ library\lib\armeabi
+ 1
+
+
+
+
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ res\drawable-normal
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-large
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ Contents
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+
+
+ res\drawable-small
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+
+
+ 0
+
+
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 0
+ .bpl
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-xlarge
+ 1
+
+
+
+
+ res\drawable-ldpi
+ 1
+
+
+
+
+ 0
+ .dll;.bpl
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ False
+
+
+ 12
+
+
+
+
+
diff --git a/components/detours/Demo/DetoursDemo/win32api/Demo2/uMain.dfm b/components/detours/Demo/DetoursDemo/win32api/Demo2/uMain.dfm
new file mode 100644
index 00000000..17a0c0b5
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/win32api/Demo2/uMain.dfm
@@ -0,0 +1,61 @@
+object Main: TMain
+ Left = 0
+ Top = 0
+ BorderStyle = bsSizeToolWin
+ Caption = 'Hooking GetSysColor function'
+ ClientHeight = 234
+ ClientWidth = 219
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ OldCreateOrder = False
+ OnCreate = FormCreate
+ PixelsPerInch = 96
+ TextHeight = 13
+ object Label1: TLabel
+ Left = 16
+ Top = 141
+ Width = 31
+ Height = 13
+ Caption = 'Label1'
+ end
+ object Memo1: TMemo
+ Left = 16
+ Top = 40
+ Width = 185
+ Height = 89
+ Lines.Strings = (
+ 'Select me before hooking , and '
+ 'reselect me after hooking !')
+ TabOrder = 0
+ end
+ object Edit1: TEdit
+ Left = 16
+ Top = 13
+ Width = 185
+ Height = 21
+ TabOrder = 1
+ Text = 'Select Me..'
+ end
+ object BtnEnableHook: TButton
+ Left = 16
+ Top = 169
+ Width = 185
+ Height = 25
+ Caption = 'Enable Hook'
+ TabOrder = 2
+ OnClick = BtnEnableHookClick
+ end
+ object BtnDisableHook: TButton
+ Left = 16
+ Top = 200
+ Width = 185
+ Height = 25
+ Caption = 'Disable Hook'
+ TabOrder = 3
+ OnClick = BtnDisableHookClick
+ end
+end
diff --git a/components/detours/Demo/DetoursDemo/win32api/Demo2/uMain.pas b/components/detours/Demo/DetoursDemo/win32api/Demo2/uMain.pas
new file mode 100644
index 00000000..08577913
--- /dev/null
+++ b/components/detours/Demo/DetoursDemo/win32api/Demo2/uMain.pas
@@ -0,0 +1,65 @@
+unit uMain;
+
+interface
+
+uses
+ Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
+ Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, DDetours;
+
+type
+ TMain = class(TForm)
+ Memo1: TMemo;
+ Edit1: TEdit;
+ BtnEnableHook: TButton;
+ BtnDisableHook: TButton;
+ Label1: TLabel;
+ procedure BtnEnableHookClick(Sender: TObject);
+ procedure BtnDisableHookClick(Sender: TObject);
+ procedure FormCreate(Sender: TObject);
+ private
+ { Private declarations }
+ public
+ { Public declarations }
+ end;
+
+var
+ Main: TMain;
+
+implementation
+
+{$R *.dfm}
+
+var
+ TrampolineGetSysColor: function(nIndex: Integer): DWORD;
+stdcall = nil;
+
+function InterceptGetSysColor(nIndex: Integer): DWORD; stdcall;
+begin
+ if nIndex = COLOR_HIGHLIGHT then
+ Result := clWebOrange
+ else
+ Result := TrampolineGetSysColor(nIndex);
+end;
+
+procedure TMain.BtnEnableHookClick(Sender: TObject);
+begin
+ @TrampolineGetSysColor := InterceptCreate(@GetSysColor, @InterceptGetSysColor);
+ Label1.Caption := 'GetSysColor is hooked.';
+end;
+
+procedure TMain.FormCreate(Sender: TObject);
+begin
+ Label1.Caption := 'GetSysColor not hooked.';
+end;
+
+procedure TMain.BtnDisableHookClick(Sender: TObject);
+begin
+ if Assigned(TrampolineGetSysColor) then
+ begin
+ InterceptRemove(@TrampolineGetSysColor);
+ TrampolineGetSysColor := nil;
+ Label1.Caption := 'GetSysColor not hooked.';
+ end;
+end;
+
+end.
diff --git a/components/detours/Demo/InstDecodeDemo/Demo1/Demo1.dpr b/components/detours/Demo/InstDecodeDemo/Demo1/Demo1.dpr
new file mode 100644
index 00000000..f6a418d9
--- /dev/null
+++ b/components/detours/Demo/InstDecodeDemo/Demo1/Demo1.dpr
@@ -0,0 +1,57 @@
+// JCL_DEBUG_EXPERT_GENERATEJDBG OFF
+program Demo1;
+
+{$APPTYPE CONSOLE}
+{$R *.res}
+
+uses
+ System.SysUtils,
+ InstDecode in '..\..\..\Source\InstDecode.pas';
+
+procedure Foo;
+asm
+ {$IFDEF CPUX64}
+ PUSH RAX
+ XOR EAX,EAX
+ MOV EAX,5
+ ADD EAX,EDX
+ POP RAX
+ NOP
+ NOP
+ NOP
+ MOV RAX,1
+ {$ELSE !CPUX64}
+ PUSH EAX
+ XOR EAX,EAX
+ MOV EAX,5
+ ADD EAX,EDX
+ POP EAX
+ NOP
+ NOP
+ NOP
+ MOV EAX,1
+ {$ENDIF CPUX64}
+end;
+
+var
+ Inst: TInstruction;
+ nInst: Integer;
+
+begin
+ // Foo;
+ Inst := Default (TInstruction);
+ Inst.Archi := CPUX;
+ Inst.NextInst := @Foo;
+ nInst := 0;
+ while (Inst.OpType <> otRET) do
+ begin
+ inc(nInst);
+ Inst.Addr := Inst.NextInst;
+ DecodeInst(@Inst);
+ Writeln(Format('OpCode : 0x%.2x | Length : %d', [Inst.OpCode, Inst.InstSize]));
+ end;
+ Writeln('-------------------------------');
+ Writeln(Format('Total instructions : %d', [nInst]));
+ ReadLn;
+
+end.
diff --git a/components/detours/Demo/InstDecodeDemo/Demo1/Demo1.dproj b/components/detours/Demo/InstDecodeDemo/Demo1/Demo1.dproj
new file mode 100644
index 00000000..df00068d
--- /dev/null
+++ b/components/detours/Demo/InstDecodeDemo/Demo1/Demo1.dproj
@@ -0,0 +1,623 @@
+
+
+ {6D1CA670-4437-4814-9FD1-01AC3CE12603}
+ 18.1
+ None
+ Demo1.dpr
+ True
+ Debug
+ Win32
+ 1
+ Console
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ $(BDS)\bin\delphi_PROJECTICON.ico
+ $(BDS)\bin\delphi_PROJECTICNS.icns
+ Demo1
+ System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
+ .\$(Platform)\$(Config)
+ .\$(Platform)\$(Config)
+ false
+ false
+ false
+ false
+ false
+
+
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png
+ true
+ true
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png
+ true
+ true
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png
+ true
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png
+ true
+ true
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png
+ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png
+ true
+ true
+ true
+ $(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png
+
+
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_80x80.png
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_60x60.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_76x76.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_40x40.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_768x1024.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_1024x768.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_152x152.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_2048x1536.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_1536x2048.png
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_40x40.png
+
+
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_80x80.png
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_60x60.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_76x76.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_40x40.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_768x1024.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_1024x768.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_152x152.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_2048x1536.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_1536x2048.png
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_40x40.png
+
+
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_80x80.png
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_60x60.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_76x76.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_40x40.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_768x1024.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_1024x768.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_152x152.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageLandscape_2048x1536.png
+ $(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImagePortrait_1536x2048.png
+ $(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_40x40.png
+
+
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;CloudService;IndyIPCommon;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;svnui;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;vclactnband;FMXTee;soaprtl;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;emsclient;VCLRESTComponents;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;Intraweb;VclSmp;DataSnapConnectors;DataSnapServerMidas;DBXFirebirdDriver;dsnapcon;inet;fmxobj;FireDACMySQLDriver;soapmidas;vclx;svn;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;dbexpress;FireDACMSAccDriver;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage)
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
+ true
+ 1033
+
+
+ FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;FireDACPgDriver;fmx;IndySystem;TeeDB;tethering;vclib;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DBXSybaseASEDriver;DbxCommonDriver;vclimg;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;DBXOracleDriver;CustomIPTransport;vclribbon;dsnap;IndyIPServer;fmxase;vcl;IndyCore;DBXMSSQLDriver;CloudService;IndyIPCommon;FmxTeeUI;FireDACIBDriver;DataSnapFireDAC;FireDACDBXDriver;soapserver;inetdbxpress;dsnapxml;FireDACInfxDriver;FireDACDb2Driver;adortl;FireDACASADriver;bindcompfmx;FireDACODBCDriver;RESTBackendComponents;emsclientfiredac;rtl;dbrtl;DbxClientDriver;FireDACCommon;bindcomp;inetdb;Tee;DBXOdbcDriver;vclFireDAC;xmlrtl;DataSnapNativeClient;ibxpress;IndyProtocols;DBXMySQLDriver;FireDACCommonDriver;bindcompdbx;bindengine;vclactnband;FMXTee;soaprtl;TeeUI;bindcompvcl;vclie;FireDACADSDriver;vcltouch;emsclient;VCLRESTComponents;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;Intraweb;VclSmp;DataSnapConnectors;DataSnapServerMidas;DBXFirebirdDriver;dsnapcon;inet;fmxobj;FireDACMySQLDriver;soapmidas;vclx;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;dbexpress;FireDACMSAccDriver;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage)
+ true
+
+
+ DEBUG;$(DCC_Define)
+ true
+ false
+ true
+ true
+ true
+
+
+ false
+
+
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+
+ MainSource
+
+
+
+ Cfg_2
+ Base
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+
+ Delphi.Personality.12
+ Application
+
+
+
+ Demo1.dpr
+
+
+
+
+
+ Demo1.exe
+ true
+
+
+
+
+ true
+
+
+
+
+ true
+
+
+
+
+ true
+
+
+
+
+ true
+
+
+
+
+ 1
+
+
+ 1
+
+
+
+
+ Contents\Resources
+ 1
+
+
+
+
+ classes
+ 1
+
+
+
+
+ res\drawable-xxhdpi
+ 1
+
+
+
+
+ Contents\MacOS
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+
+
+ library\lib\mips
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+ 1
+
+
+
+
+ 0
+
+
+ Contents\MacOS
+ 1
+ .framework
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+ ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ library\lib\armeabi
+ 1
+
+
+
+
+ 0
+
+
+ 1
+
+
+ Contents\MacOS
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ res\drawable-normal
+ 1
+
+
+
+
+ res\drawable-xhdpi
+ 1
+
+
+
+
+ res\drawable-large
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+ ..\
+ 1
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ res\drawable-hdpi
+ 1
+
+
+
+
+ Contents
+ 1
+
+
+
+
+ ..\
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ res\values
+ 1
+
+
+
+
+ res\drawable-small
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+ 1
+
+
+
+
+ res\drawable
+ 1
+
+
+
+
+ 0
+
+
+ 0
+
+
+ Contents\Resources\StartUp\
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+
+
+ library\lib\armeabi-v7a
+ 1
+
+
+
+
+ 0
+ .bpl
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+
+
+ res\drawable-mdpi
+ 1
+
+
+
+
+ res\drawable-xlarge
+ 1
+
+
+
+
+ res\drawable-ldpi
+ 1
+
+
+
+
+ 0
+ .dll;.bpl
+
+
+ 1
+ .dylib
+
+
+ Contents\MacOS
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+ 1
+ .dylib
+
+
+
+
+
+
+
+
+
+
+
+
+ False
+ False
+ False
+ False
+ False
+ True
+ False
+
+
+ 12
+
+
+
+
+
diff --git a/components/detours/Source/CPUID.pas b/components/detours/Source/CPUID.pas
new file mode 100644
index 00000000..e1ccaff2
--- /dev/null
+++ b/components/detours/Source/CPUID.pas
@@ -0,0 +1,279 @@
+// **************************************************************************************************
+// CPUID for Delphi.
+// Unit CPUID
+// https://github.com/MahdiSafsafi/delphi-detours-library
+
+// The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License");
+// you may not use this file except in compliance with the License. You may obtain a copy of the
+// License at http://www.mozilla.org/MPL/
+//
+// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
+// ANY KIND, either express or implied. See the License for the specific language governing rights
+// and limitations under the License.
+//
+// The Original Code is CPUID.pas.
+//
+// The Initial Developer of the Original Code is Mahdi Safsafi [SMP3].
+// Portions created by Mahdi Safsafi . are Copyright (C) 2013-2017 Mahdi Safsafi .
+// All Rights Reserved.
+//
+// **************************************************************************************************
+
+unit CPUID;
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+interface
+
+{$I Defs.inc}
+
+uses SysUtils;
+
+type
+ { Do not change registers order ! }
+ TCPUIDStruct = packed record
+ rEAX: UInt32; { EAX Register }
+ rEBX: UInt32; { EBX Register }
+ rEDX: UInt32; { EDX Register }
+ rECX: UInt32; { ECX Register }
+ end;
+
+ PCPUIDStruct = ^TCPUIDStruct;
+
+procedure CallCPUID(const ID: NativeUInt; var CPUIDStruct: TCPUIDStruct);
+function IsCPUIDSupported: Boolean;
+
+type
+ TCPUVendor = (vUnknown, vIntel, vAMD, vNextGen);
+ TCPUEncoding = set of (REX, VEX, EVEX);
+ TCPUInstructions = set of (iMultiNop);
+
+var
+ CPUVendor: TCPUVendor;
+ CPUEncoding: TCPUEncoding;
+ CPUInsts: TCPUInstructions;
+
+implementation
+
+var
+ CPUIDSupported: Boolean = False;
+
+function ___IsCPUIDSupported: Boolean;
+asm
+ {$IFDEF CPUX86}
+ PUSH ECX
+ PUSHFD
+ POP EAX { EAX = EFLAGS }
+ MOV ECX, EAX { Save the original EFLAGS value . }
+ {
+ CPUID is supported only if we can modify
+ bit 21 of EFLAGS register !
+ }
+ XOR EAX, $200000
+ PUSH EAX
+ POPFD { Set the new EFLAGS value }
+ PUSHFD
+ POP EAX { Read EFLAGS }
+ {
+ Check if the 21 bit was modified !
+ If so ==> Return True .
+ else ==> Return False.
+ }
+ XOR EAX, ECX
+ SHR EAX, 21
+ AND EAX, 1
+ PUSH ECX
+ POPFD { Restore original EFLAGS value . }
+ POP ECX
+ {$ELSE !CPUX86}
+ PUSH RCX
+ MOV RCX,RCX
+ PUSHFQ
+ POP RAX
+ MOV RCX, RAX
+ XOR RAX, $200000
+ PUSH RAX
+ POPFQ
+ PUSHFQ
+ POP RAX
+ XOR RAX, RCX
+ SHR RAX, 21
+ AND RAX, 1
+ PUSH RCX
+ POPFQ
+ POP RCX
+ {$ENDIF CPUX86}
+end;
+
+procedure ___CallCPUID(const ID: NativeInt; var CPUIDStruct);
+asm
+ {
+ ALL REGISTERS (rDX,rCX,rBX) MUST BE SAVED BEFORE
+ EXECUTING CPUID INSTRUCTION !
+ }
+ {$IFDEF CPUX86}
+ PUSH EDI
+ PUSH ECX
+ PUSH EBX
+ MOV EDI,EDX
+ CPUID
+ {$IFNDEF FPC}
+ MOV EDI.TCPUIDStruct.rEAX,EAX
+ MOV EDI.TCPUIDStruct.rEBX,EBX
+ MOV EDI.TCPUIDStruct.rECX,ECX
+ MOV EDI.TCPUIDStruct.rEDX,EDX
+ {$ELSE FPC}
+ MOV [EDI].TCPUIDStruct.rEAX,EAX
+ MOV [EDI].TCPUIDStruct.rEBX,EBX
+ MOV [EDI].TCPUIDStruct.rECX,ECX
+ MOV [EDI].TCPUIDStruct.rEDX,EDX
+ {$ENDIF !FPC}
+ POP EBX
+ POP ECX
+ POP EDI
+ {$ELSE !CPUX86}
+ PUSH R9
+ PUSH RBX
+ PUSH RDX
+ MOV RAX,RCX
+ MOV R9,RDX
+ CPUID
+ MOV R9.TCPUIDStruct.rEAX,EAX
+ MOV R9.TCPUIDStruct.rEBX,EBX
+ MOV R9.TCPUIDStruct.rECX,ECX
+ MOV R9.TCPUIDStruct.rEDX,EDX
+ POP RDX
+ POP RBX
+ POP R9
+ {$ENDIF CPUX86}
+end;
+
+function ___IsAVXSupported: Boolean;
+asm
+ {
+ Checking for AVX support requires 3 steps:
+
+ 1) Detect CPUID.1:ECX.OSXSAVE[bit 27] = 1
+ => XGETBV enabled for application use
+
+ 2) Detect CPUID.1:ECX.AVX[bit 28] = 1
+ => AVX instructions supported.
+
+ 3) Issue XGETBV and verify that XCR0[2:1] = ‘11b’
+ => XMM state and YMM state are enabled by OS.
+
+ }
+
+ { Steps : 1 and 2 }
+ {$IFDEF CPUX64}
+ MOV RAX, 1
+ PUSH RCX
+ PUSH RBX
+ PUSH RDX
+ {$ELSE !CPUX64}
+ MOV EAX, 1
+ PUSH ECX
+ PUSH EBX
+ PUSH EDX
+ {$ENDIF CPUX64}
+ CPUID
+ AND ECX, $018000000
+ CMP ECX, $018000000
+ JNE @@NOT_SUPPORTED
+ XOR ECX,ECX
+ {
+ Delphi does not support XGETBV !
+ => We need to use the XGETBV opcodes !
+ }
+ DB $0F DB $01 DB $D0 // XGETBV
+ { Step :3 }
+ AND EAX, $06
+ CMP EAX, $06
+ JNE @@NOT_SUPPORTED
+ MOV EAX, 1
+ JMP @@END
+@@NOT_SUPPORTED:
+ XOR EAX,EAX
+@@END:
+ {$IFDEF CPUX64}
+ POP RDX
+ POP RBX
+ POP RCX
+ {$ELSE !CPUX64}
+ POP EDX
+ POP EBX
+ POP ECX
+ {$ENDIF CPUX64}
+end;
+
+procedure CallCPUID(const ID: NativeUInt; var CPUIDStruct: TCPUIDStruct);
+begin
+ FillChar(CPUIDStruct, SizeOf(TCPUIDStruct), #0);
+ if not CPUIDSupported then
+ raise Exception.Create('CPUID instruction not supported.')
+ else
+ ___CallCPUID(ID, CPUIDStruct);
+end;
+
+function IsCPUIDSupported: Boolean;
+begin
+ Result := CPUIDSupported;
+end;
+
+type
+ TVendorName = array [0 .. 12] of AnsiChar;
+
+function GetVendorName: TVendorName;
+var
+ Info: PCPUIDStruct;
+ P: PByte;
+begin
+ Result := '';
+ if not IsCPUIDSupported then
+ Exit;
+ Info := GetMemory(SizeOf(TCPUIDStruct));
+ CallCPUID(0, Info^);
+ P := PByte(Info) + 4; // Skip EAX !
+ Move(P^, PByte(@Result[0])^, 12);
+ FreeMemory(Info);
+end;
+
+procedure __Init__;
+var
+ vn: TVendorName;
+ Info: TCPUIDStruct;
+ r: UInt32;
+begin
+ CPUVendor := vUnknown;
+{$IFDEF CPUX64}
+ CPUEncoding := [REX];
+{$ELSE !CPUX64}
+ CPUEncoding := [];
+{$ENDIF CPUX64}
+ CPUInsts := [];
+ if IsCPUIDSupported then
+ begin
+ vn := GetVendorName();
+ if vn = 'GenuineIntel' then
+ CPUVendor := vIntel
+ else if vn = 'AuthenticAMD' then
+ CPUVendor := vAMD
+ else if vn = 'NexGenDriven' then
+ CPUVendor := vNextGen;
+ CallCPUID(1, Info);
+ r := Info.rEAX and $F00;
+ case r of
+ $F00, $600: Include(CPUInsts, iMultiNop);
+ end;
+ if ___IsAVXSupported then
+ Include(CPUEncoding, VEX);
+ end;
+end;
+
+initialization
+
+CPUIDSupported := ___IsCPUIDSupported;
+__Init__;
+
+end.
diff --git a/components/detours/Source/DDetours.pas b/components/detours/Source/DDetours.pas
new file mode 100644
index 00000000..b69c799d
--- /dev/null
+++ b/components/detours/Source/DDetours.pas
@@ -0,0 +1,2861 @@
+// **************************************************************************************************
+// Delphi Detours Library.
+// Unit DDetours
+// https://github.com/MahdiSafsafi/delphi-detours-library
+
+// The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License");
+// you may not use this file except in compliance with the License. You may obtain a copy of the
+// License at http://www.mozilla.org/MPL/
+//
+// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
+// ANY KIND, either express or implied. See the License for the specific language governing rights
+// and limitations under the License.
+//
+// The Original Code is DDetours.pas.
+//
+// Contributor(s):
+// David Millington
+// RRUZ
+//
+// The Initial Developer of the Original Code is Mahdi Safsafi [SMP3].
+// Portions created by Mahdi Safsafi . are Copyright (C) 2013-2017 Mahdi Safsafi .
+// All Rights Reserved.
+//
+// **************************************************************************************************
+
+{ ===============================> CHANGE LOG <======================================================
+
+ Jan 24,2015:
+ +Added support for vtable patching.
+ +Added GetNHook/IsHooked support for Interface.
+
+ Jan 20,2015:
+ +Added support to hook Delphi Interface by name.
+
+ Version2 , Mahdi Safsafi:
+ +Many bug fix.
+ +Added new hooking model architecture.
+ +Added multi hook support.
+ +Added COM hook support.
+ +Added instruction maping feature.
+ +Added hook detecting feature.
+ +Added BeginHooks/EndHooks.
+ +Added BeginUnHooks/EndUnHooks.
+ +Added IDetours interface.
+ +Added MultiNop instructions support.
+ +Generate better opcodes.
+ +Improved support for x64.
+ +Improved AllocMemAt function.
+ ====================================================================================================== }
+
+unit DDetours;
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+interface
+
+{$I Defs.inc}
+
+uses
+ InstDecode,
+ CPUID,
+ SysUtils,
+{$IFDEF DXE2UP}
+ WinApi.Windows,
+{$ELSE !DXE2UP}
+ Windows,
+{$ENDIF DXE2UP}
+ Classes
+{$IFDEF MustUseGenerics}
+ , Generics.Collections //
+ , Typinfo, RTTI
+{$ENDIF MustUseGenerics}
+ ;
+
+type
+ InterceptException = Exception;
+{$IFNDEF DXE2UP}
+ SIZE_T = NativeUInt;
+{$ENDIF !DXE2UP}
+
+const
+ { Maximum allowed number of hooks. }
+ MAX_HOOKS = 7;
+
+ { Options }
+ Root = 1; // Future use.
+ ST = 2; // Suspend Threads.
+
+{$IFDEF BuildThreadSafe}
+ {
+ Make the new version compatible with the old one !
+ ===================================================
+ I don't guarantee that i will continue
+ supporting old release .
+ ==> You sould update your code
+ when you have some time !
+ }
+ v1compatibility = ST;
+{$ELSE !BuildThreadSafe}
+ v1compatibility = 0;
+{$ENDIF BuildThreadSafe}
+ { ======================================================================================================================================================= }
+function InterceptCreate(const TargetProc, InterceptProc: Pointer; Options: Byte = v1compatibility): Pointer; overload;
+function InterceptCreate(const TargetInterface; MethodIndex: Integer; const InterceptProc: Pointer; Options: Byte = v1compatibility): Pointer; overload;
+function InterceptCreate(const Module, MethodName: String; const InterceptProc: Pointer; ForceLoadModule: Boolean = True; Options: Byte = v1compatibility)
+ : Pointer; overload;
+procedure InterceptCreate(const TargetProc, InterceptProc: Pointer; var TrampoLine: Pointer; Options: Byte = v1compatibility); overload;
+function InterceptRemove(const Trampo: Pointer; Options: Byte = v1compatibility): Integer;
+function GetNHook(const TargetProc: Pointer): ShortInt; overload;
+function GetNHook(const TargetInterface; MethodIndex: Integer): ShortInt; overload;
+function IsHooked(const TargetProc: Pointer): Boolean; overload;
+function IsHooked(const TargetInterface; MethodIndex: Integer): Boolean; overload;
+function PatchVt(const TargetInterface; MethodIndex: Integer; InterceptProc: Pointer): Pointer;
+function UnPatchVt(const Trampo: Pointer): Boolean;
+
+{$IFDEF MustUseGenerics }
+function InterceptCreate(const TargetInterface; const MethodName: String; const InterceptProc: Pointer; Options: Byte = v1compatibility): Pointer; overload;
+function GetNHook(const TargetInterface; const MethodName: String): ShortInt; overload;
+function IsHooked(const TargetInterface; const MethodName: String): Boolean; overload;
+function BeginHooks(): Boolean;
+function EndHooks(): Boolean;
+function BeginUnHooks(): Boolean;
+function EndUnHooks(): Boolean;
+
+type
+ DetourException = Exception;
+
+ IGenericCast = interface(IInterface)
+ ['{B19D793C-3225-439C-A2F3-04A72D41879E}']
+ function TToPointer(const _T: T): Pointer;
+ function PointerToT(const _P: Pointer): T;
+ end;
+
+ IDetours = interface(IInterface)
+ ['{04552E96-C716-4378-BE9A-CD383D20AB91}']
+ function NextHook: T;
+ function GetInstalled: Boolean;
+ function GetHookCount: ShortInt;
+ procedure SetHook(const TargetProc, InterceptProc: T);
+ procedure Enable;
+ procedure Disable;
+ property TrampoLine: T read NextHook; // Call the original
+ end;
+
+ TDetours = class(TInterfacedObject, IGenericCast, IDetours)
+ private
+ FTargetProc: PByte;
+ FInterceptProc: PByte;
+ FNextHook: T;
+ function __TToPointer(const _T): Pointer;
+ function __PointerToT(const _P): T;
+ function TToPointer(const _T: T): Pointer;
+ function PointerToT(const _P: Pointer): T;
+ function NextHook: T;
+ function GetInstalled: Boolean;
+ function GetHookCount: ShortInt;
+ protected
+ function CheckTType: Boolean;
+ procedure SetHook(const TargetProc, InterceptProc: T);
+ public
+ constructor Create(const TargetProc, InterceptProc: T);
+ destructor Destroy; override;
+ procedure Enable;
+ procedure Disable;
+ property TrampoLine: T read NextHook; // Call the original
+ property Installed: Boolean read GetInstalled;
+ property nHook: ShortInt read GetHookCount;
+ end;
+
+const
+ SInvalidTType = '%s must be procedure.';
+ SDetoursNotInstalled = 'Detour is not installed; trampoline pointer is nil';
+{$ENDIF MustUseGenerics }
+{$IFDEF FPC}
+
+var
+ Critical: TRTLCriticalSection;
+{$ENDIF FPC}
+
+implementation
+
+{$OVERFLOWCHECKS OFF}
+{$IFNDEF FPC}
+
+{ Delphi }
+uses
+{$IFDEF DXE2UP}
+ WinApi.TLHelp32;
+{$ELSE !DXE2UP}
+ TLHelp32;
+{$ENDIF DXE2UP}
+{$ELSE FPC}
+
+type
+ tagTHREADENTRY32 = record
+ dwSize: DWORD;
+ cntUsage: DWORD;
+ th32ThreadID: DWORD; // this thread
+ th32OwnerProcessID: DWORD; // Process this thread is associated with
+ tpBasePri: Longint;
+ tpDeltaPri: Longint;
+ dwFlags: DWORD;
+ end;
+
+ THREADENTRY32 = tagTHREADENTRY32;
+ PTHREADENTRY32 = ^tagTHREADENTRY32;
+ LPTHREADENTRY32 = ^tagTHREADENTRY32;
+ TThreadEntry32 = tagTHREADENTRY32;
+
+ TCreateToolhelp32Snapshot = function(dwFlags, th32ProcessID: DWORD): THandle stdcall;
+ TThread32First = function(hSnapshot: THandle; var lpte: TThreadEntry32): BOOL stdcall;
+ TThread32Next = function(hSnapshot: THandle; var lpte: TThreadEntry32): BOOL stdcall;
+
+var
+ CreateToolhelp32Snapshot: TCreateToolhelp32Snapshot;
+ Thread32First: TThread32First;
+ Thread32Next: TThread32Next;
+
+const
+ TH32CS_SNAPTHREAD = $00000004;
+{$ENDIF !FPC}
+
+type
+ TOpenThread = function(dwDesiredAccess: DWORD; bInheritHandle: BOOL; dwThreadId: DWORD): THandle; stdcall;
+
+var
+ OpenThread: TOpenThread;
+ hKernel: THandle;
+ OpenThreadExist: Boolean = False;
+ FreeKernel: Boolean = False;
+ SizeOfAlloc: DWORD = 0; // See initialization !
+
+const
+ { Instructions OpCodes }
+ opJmpRelz = $E9;
+ opJmpRelb = $EB;
+ opJmpMem = $25FF;
+ opTestb = $85;
+ opPrfOpSize = $66;
+ opPrfAddrSize = $67;
+ opNop = $90;
+
+ fDscrHasTmp = $01;
+ DscrSigSize = $08;
+ TrampoSize = 64;
+ TmpSize = 32;
+
+type
+ TDscrSig = array [0 .. DscrSigSize - 1] of Byte;
+ TTrampoData = array [0 .. TrampoSize - 1] of Byte;
+
+ TVirtualProtect = function(lpAddress: Pointer; dwSize: SIZE_T; flNewProtect: DWORD; var OldProtect: DWORD): BOOL; stdcall;
+ TVirtualAlloc = function(lpvAddress: Pointer; dwSize: SIZE_T; flAllocationType, flProtect: DWORD): Pointer; stdcall;
+ TVirtualQuery = function(lpAddress: Pointer; var lpBuffer: TMemoryBasicInformation; dwLength: SIZE_T): SIZE_T; stdcall;
+ TFlushInstructionCache = function(hProcess: THandle; const lpBaseAddress: Pointer; dwSize: SIZE_T): BOOL; stdcall;
+ TGetCurrentProcess = function: THandle; stdcall;
+ TVirtualFree = function(lpAddress: Pointer; dwSize: SIZE_T; dwFreeType: DWORD): BOOL; stdcall;
+
+ TInternalFuncs = record
+ VirtualAlloc: TVirtualAlloc;
+ VirtualFree: TVirtualFree;
+ VirtualProtect: TVirtualProtect;
+ VirtualQuery: TVirtualQuery;
+ FlushInstructionCache: TFlushInstructionCache;
+ GetCurrentProcess: TGetCurrentProcess;
+ end;
+
+var
+ InternalFuncs: TInternalFuncs;
+
+const
+ { Descriptor Signature }
+{$IFDEF CPUX64}
+ DscrSig: TDscrSig = ( //
+ $90, { NOP }
+ $40, { REX }
+ $40, { REX }
+ $40, { REX }
+ $0F, { ESCAPE TWO BYTE }
+ $1F, { HINT_NOP }
+ $F3, { PRF }
+ $F3 { PRF }
+ );
+{$ELSE !CPUX64}
+ DscrSig: TDscrSig = ( //
+ $90, { NOP }
+ $40, { INC EAX }
+ $48, { DEC EAX }
+ $90, { NOP }
+ $0F, { ESCAPE TWO BYTE }
+ $1F, { HINT_NOP }
+ $F3, { PRF }
+ $F3 { PRF }
+ );
+{$ENDIF CPUX64}
+
+type
+ TTrampoInfo = record
+ Addr: PByte; // Pointer to first trampoline instruction .
+ Size: Byte; // Stolen bytes size .
+ PData: PByte; // Original Stolen bytes.
+ end;
+
+ PTrampoInfo = ^TTrampoInfo;
+
+ TJmpMem = packed record
+ OpCode: WORD; // $0F$25
+ Disp32: Integer;
+ end;
+
+ PJmpMem = ^TJmpMem;
+
+ TDescriptor = packed record
+ Sig: TDscrSig; { Table signature. }
+ DscrAddr: PByte; { Pointer that hold jmp address (if Used)! }
+ nHook: Byte; { Number of hooks . }
+ Flags: Byte; { Reserved for future use! }
+ ExMem: PByte; { Reserved for jmp (if used) & for Trampoline ! }
+ OrgPtr: PByte; { Original Target Proc address. }
+ Trampo: PTrampoInfo; { Pointer to TrampoInfo struct. }
+ { Array that hold jmp destination address. }
+ JmpAddrs: array [0 .. MAX_HOOKS] of PByte;
+ {
+ Mark the beginning of descriptor code executing .
+ ==> Must be NOP .
+ }
+ CodeEntry: Byte;
+ { Jmp Instruction for NextHook call and Trampoline call ! }
+ JmpMems: array [0 .. MAX_HOOKS] of TJmpMem;
+ end;
+
+ PDescriptor = ^TDescriptor;
+
+ TNextHook = packed record
+ ID: Byte; { Hook ID . }
+ PDscr: PDescriptor;
+ end;
+
+ PNextHook = ^TNextHook;
+
+ TThreadsIDList = class(TList);
+
+ TInterceptMonitor = class(TObject)
+ class procedure InternalCreate;
+ class procedure InternalDestroy;
+ class var FLock: TObject;
+ class procedure Enter;
+ class procedure Leave;
+ end;
+
+ TIntercept = class(TObject)
+ private
+ FOptions: Byte;
+ FList: TThreadsIDList;
+ class function GetRoot(P: PByte): PByte;
+ public
+ constructor Create(Options: Byte); virtual;
+ destructor Destroy; override;
+
+ protected
+ function GetDescriptor(P: PByte): PDescriptor;
+ function IsValidDescriptor(P: PByte): Boolean;
+ function CreateNewDescriptor: PDescriptor;
+ procedure InsertDescriptor(PAt: PByte; PDscr: PDescriptor);
+ procedure RemoveDescriptor(PDscr: PDescriptor);
+ function InstallHook(TargetProc, InterceptProc: PByte; const Options: Byte = $00): PByte;
+ function AddHook(PDscr: PDescriptor; InterceptProc: PByte; const Options: Byte = $00): PByte;
+ function RemoveHook(Trampo: PByte): Integer;
+ end;
+
+const
+ { Error Str }
+ ErrFuncSize = 'Size of function is too small, risk to override others adjacent functions.';
+ ErrJmpInvalid = 'Invalid JMP Type.';
+ ErrJmpInvalid64 = 'Invalid JMP Type for x64.';
+ ErrJmpInvalid32 = 'Invalid JMP Type for x32.';
+ ErrJmpInvalidDstSave = 'Invalid DstSave Address pointer.';
+ ErrMultiNopNotSup = 'Multi Bytes Nop Instructions not supported by your CPU.';
+ ErrRipDisp = 'Failed to correcr RIP Displacement.';
+ ErrTrampoSize = 'Exceed maximum TrampoSize.';
+ ErrMaxHook = 'Exceed maximum allowed of hooks.';
+ ErrTargetProc = 'Invalid TargetProc Pointer.';
+ ErrInterceptProc = 'Invalid InterceptProc Pointer.';
+ ErrInvalidDscr = 'Invalid Descriptor.';
+ ErrInvalidTrampo = 'Invalid TrampoLine Pointer.';
+ ErrBgnUnHooks = 'BeginUnHooks must be called outside BeginHooks/EndHooks.';
+
+ { JMP Type }
+ tJmpNone = 0;
+ tJmpRel8 = 1;
+ tJmpRel16 = 2;
+ tJmpRel32 = 3;
+ tJmpMem16 = 4;
+ tJmpMem32 = 5;
+ tJmpMem64 = 6;
+ tJmpRipZ = 7;
+
+{$IFDEF CPUX64}
+ tJmpMemN = tJmpMem64;
+{$ELSE !CPUX64}
+ tJmpMemN = tJmpMem32;
+{$ENDIF CPUX64}
+ { Jmp Type To Size }
+ JmpTypeToSize: array [0 .. 7] of Byte = ( //
+ 0, { None }
+ 2, { tJmpRel8 = $EB + Rel8 }
+ 4, { tJmpRel16 = OpSizePrf + $E9 + Rel16 }
+ 5, { tJmpRel32 = $E9 + Rel32 }
+ 7, { tJmpMem16 = OpSizePrf + $FF /4 + Disp32 }
+ 6, { tJmpMem32 = $FF /4 + Disp32 }
+ 6, { tJmpMem64 = $FF /4 + Disp32 }
+ 14 { tJmpRipZ = $FF /4 + Disp32 + DQ }
+ );
+
+ SizeToJmpType: array [0 .. 4] of Byte = ( //
+{$IFDEF CPUX86}
+ tJmpRel8, { db }
+ tJmpRel16, { dw }
+ tJmpRel32, { dd }
+ tJmpMem32, { dd }
+ tJmpMem32 { dd }
+{$ELSE !CPUX86}
+ tJmpRel8, { db }
+ tJmpRel32, { dw }
+ tJmpRel32, { dd }
+ tJmpMem64, { dq }
+ tJmpMem64 { dq }
+{$ENDIF CPUX86}
+ );
+
+ {
+ // Useful function when debugging !
+ procedure DbgPrint(const msg: string; Value: Int64); overload;
+ var
+ s: string;
+ begin
+ s := msg;
+ if s <> EmptyStr then
+ s := s + ' = ' + IntToStr(Value)
+ else
+ s := IntToStr(Value);
+ OutputDebugStringW(PChar(s));
+ end;
+
+ procedure DbgPrint(const msg: string); overload;
+ begin
+ OutputDebugStringW(PChar(msg));
+ end;
+
+ procedure ShowMsg(const msg: string);
+ begin
+ MessageBoxW(0, PChar(msg), nil, MB_OK);
+ end;
+ }
+const
+ THREAD_SUSPEND_RESUME = $0002;
+
+function SuspendAllThreads(RTID: TThreadsIDList): Boolean;
+var
+ hSnap: THandle;
+ PID: DWORD;
+ te: TThreadEntry32;
+ nCount: DWORD;
+ hThread: THandle;
+ Next: Boolean;
+ CurrentThreadId: Cardinal;
+begin
+ PID := GetCurrentProcessId;
+ CurrentThreadId := GetCurrentThreadId;
+ hSnap := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, PID);
+ Result := hSnap <> INVALID_HANDLE_VALUE;
+ if Result then
+ begin
+ te.dwSize := SizeOf(TThreadEntry32);
+ Next := Thread32First(hSnap, te);
+ while Next do
+ begin
+ if (te.th32OwnerProcessID = PID) and (te.th32ThreadID <> CurrentThreadId) then
+ begin
+ { Allow the caller thread to access the Detours .
+ => Suspend all threads, except the current thread . }
+ hThread := OpenThread(THREAD_SUSPEND_RESUME, False, te.th32ThreadID);
+ if hThread <> INVALID_HANDLE_VALUE then
+ begin
+ nCount := SuspendThread(hThread);
+ if nCount <> DWORD(-1) then // thread's previously was running .
+ { Only add threads that was running before suspending them ! }
+ RTID.Add(Pointer(NativeUInt(te.th32ThreadID)));
+ CloseHandle(hThread);
+ end;
+ end;
+ Next := Thread32Next(hSnap, te);
+ end;
+ CloseHandle(hSnap);
+ end;
+end;
+
+function ResumeSuspendedThreads(RTID: TThreadsIDList): Boolean;
+var
+ i: Integer;
+ TID: DWORD;
+ hThread: THandle;
+begin
+ Result := False;
+ if Assigned(RTID) then
+ for i := 0 to RTID.Count - 1 do
+ begin
+ TID := DWORD(RTID.Items[i]);
+ if TID <> DWORD(-1) then
+ begin
+ Result := True;
+ hThread := OpenThread(THREAD_SUSPEND_RESUME, False, TID);
+ if hThread <> INVALID_HANDLE_VALUE then
+ begin
+ ResumeThread(hThread);
+ CloseHandle(hThread);
+ end;
+ end;
+ end;
+end;
+
+function SetMemPermission(const P: Pointer; const Size: NativeUInt; const NewProtect: DWORD): DWORD;
+const
+ PAGE_EXECUTE_FLAGS = PAGE_EXECUTE or PAGE_EXECUTE_READ or PAGE_EXECUTE_READWRITE or PAGE_EXECUTE_WRITECOPY;
+begin
+ Result := 0;
+ if Assigned(P) and (Size > 0) and (NewProtect > 0) then
+ begin
+ if InternalFuncs.VirtualProtect(P, Size, NewProtect, Result) then
+ if (NewProtect and PAGE_EXECUTE_FLAGS <> 0) then
+ {
+ If the protected region will be executed
+ => We need to update the cpu cache !
+ }
+ InternalFuncs.FlushInstructionCache(InternalFuncs.GetCurrentProcess(), P, Size);
+ end;
+end;
+
+function GetDispDataSize(PInst: PInstruction): ShortInt;
+begin
+ Result := 0;
+ if PInst^.Disp.Flags and dfUsed <> 0 then
+ begin
+ if PInst^.Archi = CPUX32 then
+ begin
+ if PInst^.Prefixes and Prf_OpSize <> 0 then
+ Exit(ops16bits)
+ else
+ Exit(ops32bits);
+ end else begin
+ case PInst^.OperandFlags of
+ opdD64:
+ begin
+ {
+ Defaults to O64 in PM64.
+ PrfOpSize results in O16.
+ }
+ if PInst^.Prefixes and Prf_OpSize <> 0 then
+ Exit(ops16bits)
+ else
+ Exit(ops64bits);
+ end;
+ opdF64, opdDv64:
+ begin
+ { The operand size is forced to a 64-bit operand size in PM64 ! }
+ Exit(ops64bits);
+ end;
+ opdDf64:
+ begin
+ {
+ Defaults to O64 in PM64.
+ PrfOpSize results in O16 in AMD64.
+ PrfOpSize is ignored in EM64T.
+ }
+ if (CPUVendor = vAMD) and (PInst^.Prefixes and Prf_OpSize <> 0) then
+ Exit(ops16bits)
+ else
+ Exit(ops64bits);
+ end;
+ else
+ begin
+ if PInst^.Rex.W then
+ Exit(ops64bits)
+ else if (PInst^.Prefixes and Prf_OpSize <> 0) then
+ Exit(ops16bits)
+ else
+ Exit(ops32bits);
+ end;
+ end;
+ end;
+ end;
+end;
+
+function fDecodeInst(PInst: PInstruction): ShortInt;
+var
+ IsNxtInstData: Boolean;
+begin
+ { Include VEX decoding if the cpu support it! }
+ if (VEX in CPUEncoding) then
+ PInst.Options := DecodeVex;
+
+ Result := DecodeInst(PInst);
+
+{$IFDEF CPUX64}
+ IsNxtInstData := ((PInst^.Disp.Flags and (dfUsed or dfRip) = (dfUsed or dfRip)) and (PInst^.Disp.Value = 0));
+{$ELSE !CPUX64}
+ IsNxtInstData := (PInst^.Disp.Value = UInt64(PInst^.NextInst));
+{$ENDIF CPUX64}
+ if IsNxtInstData then
+ begin
+ {
+ Check if the Next Instruction is data !
+ If so , That's mean it's not a valid instruction .
+ We must skip this data ..
+ otherwise , disassembling next instructions will fail !
+ }
+ Inc(Result, GetDispDataSize(PInst));
+ PInst^.InstSize := Result;
+ end;
+end;
+
+function RoundMultipleOf(const Value, n: NativeUInt): NativeUInt; {$IFDEF MustInline}inline; {$ENDIF}
+begin
+ if Value = 0 then
+ Exit(n);
+ Result := ((Value + (n - 1)) and not(n - 1));
+end;
+
+function AllocMemAt(const Addr: Pointer; const MemSize, flProtect: DWORD): Pointer;
+var
+ mbi: TMemoryBasicInformation;
+ SysInfo: TSystemInfo;
+ pBase: PByte;
+ P: PByte;
+ Q: PByte;
+ pMax, pMin: PByte;
+ dwAllocGran: DWORD;
+begin
+ { Alloc memory on the specific nearest address from the Addr . }
+
+ Result := nil;
+ P := PByte(Addr);
+ if not Assigned(P) then
+ begin
+ Result := InternalFuncs.VirtualAlloc(nil, MemSize, MEM_RESERVE or MEM_COMMIT, flProtect);
+ Exit;
+ end;
+
+ GetSystemInfo(SysInfo);
+ pMin := SysInfo.lpMinimumApplicationAddress;
+ pMax := SysInfo.lpMaximumApplicationAddress;
+ dwAllocGran := SysInfo.dwAllocationGranularity;
+
+ if (P < pMin) or (P > pMax) then
+ Exit;
+ if InternalFuncs.VirtualQuery(P, mbi, SizeOf(mbi)) = 0 then
+ Exit;
+
+ pBase := mbi.BaseAddress;
+ Q := pBase;
+ while Q < pMax do
+ begin
+ if InternalFuncs.VirtualQuery(Q, mbi, SizeOf(mbi)) = 0 then
+ Exit;
+ if (mbi.State = MEM_FREE) and (mbi.RegionSize >= dwAllocGran) and (mbi.RegionSize >= MemSize) then
+ begin
+ { The address (P) must be multiple of the allocation granularity (dwAllocationGranularity) . }
+ P := PByte(RoundMultipleOf(NativeUInt(Q), dwAllocGran));
+ Result := InternalFuncs.VirtualAlloc(P, MemSize, MEM_RESERVE or MEM_COMMIT, flProtect);
+ if Assigned(Result) then
+ Exit;
+ end;
+ Inc(Q, mbi.RegionSize); // Next Region .
+ end;
+ {
+ If thre is no memory available in the range [Addr - pMax]
+ try to allocate at the range [pMin - Addr]
+ }
+ Q := pBase;
+ while Q > pMin do
+ begin
+ if InternalFuncs.VirtualQuery(Q, mbi, SizeOf(mbi)) = 0 then
+ Exit;
+ if (mbi.State = MEM_FREE) and (mbi.RegionSize >= dwAllocGran) and (mbi.RegionSize >= MemSize) then
+ begin
+ P := PByte(RoundMultipleOf(NativeUInt(Q), dwAllocGran));
+ Result := InternalFuncs.VirtualAlloc(P, MemSize, MEM_RESERVE or MEM_COMMIT, flProtect);
+ if Assigned(Result) then
+ Exit;
+ end;
+ Dec(Q, mbi.RegionSize); // Previous Region.
+ end;
+end;
+
+function TryAllocMemAt(const Addr: Pointer; const MemSize, flProtect: DWORD): Pointer;
+var
+ MEM_64: DWORD;
+begin
+ MEM_64 := 0;
+ Result := AllocMemAt(Addr, MemSize, flProtect);
+ if not Assigned(Result) then
+ begin
+{$IFDEF CPUX64}
+ { Allocates memory at the highest possible address }
+ if (UInt64(Addr) and $FFFFFFFF00000000 <> 0) then
+ MEM_64 := MEM_TOP_DOWN;
+{$ENDIF CPUX64}
+ Result := InternalFuncs.VirtualAlloc(nil, MemSize, MEM_RESERVE or MEM_COMMIT or MEM_64, flProtect);
+ end;
+end;
+
+function InsertJmp(Src, Dst: PByte; JmpType: Byte; const DstSave: PByte = nil): ShortInt;
+var
+ Offset32: Int32;
+ Offset64: Int64;
+ JmpSize: Byte;
+begin
+ Result := 1;
+ JmpSize := JmpTypeToSize[JmpType];
+ Offset32 := Int32(UInt64(Dst) - UInt64(Src)) - JmpSize;
+ case JmpType of
+ tJmpNone:
+ begin
+ raise InterceptException.Create(ErrJmpInvalid);
+ end;
+ tJmpRel8:
+ begin
+ PByte(Src)^ := opJmpRelb;
+ Inc(Src);
+ PInt8(Src)^ := Int8(Offset32);
+ end;
+ tJmpRel16:
+ begin
+{$IFDEF CPUX64}
+ {
+ JMP Rel16
+ ==> Not supported on x64!
+ }
+ raise InterceptException.Create(ErrJmpInvalid64);
+{$ENDIF CPUX64}
+ PByte(Src)^ := opPrfOpSize;
+ Inc(Src);
+ PByte(Src)^ := opJmpRelz;
+ Inc(Src);
+ PInt16(Src)^ := Int16(Offset32);
+ end;
+ tJmpRel32:
+ begin
+ PByte(Src)^ := opJmpRelz;
+ Inc(Src);
+ PInt32(Src)^ := Offset32;
+ end;
+ tJmpMem16:
+ begin
+{$IFDEF CPUX64}
+ {
+ JMP WORD [012345]
+ ==> Not supported on x64!
+ }
+ raise InterceptException.Create(ErrJmpInvalid64);
+{$ENDIF CPUX64}
+ if not Assigned(DstSave) then
+ raise InterceptException.Create(ErrJmpInvalidDstSave);
+ PByte(Src)^ := opPrfOpSize;
+ Inc(Src);
+ PWord(Src)^ := opJmpMem;
+ Inc(Src, 2);
+ PUInt32(Src)^ := UInt32(DstSave);
+ PUInt16(DstSave)^ := UInt16(Dst);
+ end;
+ tJmpMem32:
+ begin
+{$IFDEF CPUX64}
+ {
+ JMP DWORD [012345]
+ ==> Not supported on x64!
+ }
+ raise InterceptException.Create(ErrJmpInvalid64);
+{$ENDIF CPUX64}
+ if not Assigned(DstSave) then
+ raise InterceptException.Create(ErrJmpInvalidDstSave);
+ PWord(Src)^ := opJmpMem;
+ Inc(Src, 2);
+ PUInt32(Src)^ := UInt32(DstSave);
+ PUInt32(DstSave)^ := UInt32(Dst);
+ end;
+ tJmpMem64:
+ begin
+{$IFDEF CPUX86}
+ {
+ JMP QWORD [0123456789]
+ ==> Not supported on x32!
+ }
+ raise InterceptException.Create(ErrJmpInvalid32);
+{$ENDIF CPUX86}
+ if not Assigned(DstSave) then
+ raise InterceptException.Create(ErrJmpInvalidDstSave);
+ { RIP Disp ! }
+ PUInt64(DstSave)^ := UInt64(Dst);
+ Offset64 := Int64(UInt64(DstSave) - UInt64(Src)) - JmpSize;
+ Offset32 := Integer(Offset64);
+ { If the distance between DispAddr and Src exceed 32-bits then
+ the only way to insert a jump
+ is to use tJmpRipZ method ! }
+ if Offset32 <> Offset64 then
+ Exit(-1);
+ PWord(Src)^ := opJmpMem;
+ Inc(Src, 2);
+ PInt32(Src)^ := Offset32;
+ end;
+ tJmpRipZ:
+ begin
+{$IFDEF CPUX86}
+ raise InterceptException.Create(ErrJmpInvalid32);
+{$ENDIF CPUX86}
+ {
+ This is the most harder way to insert a jump !
+ Why ?
+ because we are going to mix code & data !
+ Thats mean when disassembling instructions after
+ this branch .. you will have a corrupted dissambled
+ structure !
+
+ The only way to detect this kind of jmp is:
+ to use fDecodeInst rather than DecodeInst routine .
+
+ ==> We should avoid using this kind of jmp
+ in the original target proc .
+
+ ==> It's Ok to use in others situation .
+ }
+
+ PWord(Src)^ := opJmpMem;
+ Inc(Src, 2);
+ PInt32(Src)^ := $00;
+ Inc(Src, 4);
+ PUInt64(Src)^ := UInt64(Dst);
+ end;
+ end;
+end;
+
+function GetUInt64Size(const Value: UInt64): Byte;
+begin
+ if UInt8(Value) = Value then
+ Exit(1)
+ else if UInt16(Value) = Value then
+ Exit(2)
+ else if UInt32(Value) = Value then
+ Exit(4)
+ else
+ Exit(8);
+end;
+
+function GetInt64Size(const Value: Int64): Byte;
+begin
+ if Int8(Value) = Value then
+ Exit(1)
+ else if Int16(Value) = Value then
+ Exit(2)
+ else if Int32(Value) = Value then
+ Exit(4)
+ else
+ Exit(8);
+end;
+
+function GetJmpType(Src, Dst, DstSave: PByte): Byte;
+var
+ Offset: Int64;
+ OffsetSize: Byte;
+begin
+ Offset := Int64(UInt64(Src) - UInt64(Dst));
+ OffsetSize := GetInt64Size(Offset);
+ Result := SizeToJmpType[OffsetSize shr 1];
+{$IFDEF CPUX64}
+ if Result = tJmpMem64 then
+ begin
+ if not Assigned(DstSave) then
+ raise InterceptException.Create(ErrJmpInvalidDstSave);
+ Offset := Int64(UInt64(DstSave) - UInt64(Src)) - 7;
+ if Int32(Offset) <> Offset then
+ Exit(tJmpRipZ);
+ end;
+{$ENDIF CPUX64}
+end;
+
+{$IFDEF UseMultiBytesNop}
+
+const
+ Nop9: array [0 .. 8] of Byte = ($66, $0F, $1F, $84, $00, $00, $00, $00, $00);
+ Nop8: array [0 .. 7] of Byte = ($0F, $1F, $84, $00, $00, $00, $00, $00);
+ Nop7: array [0 .. 6] of Byte = ($0F, $1F, $80, $00, $00, $00, $00);
+ Nop6: array [0 .. 5] of Byte = ($66, $0F, $1F, $44, $00, $00);
+ Nop5: array [0 .. 4] of Byte = ($0F, $1F, $44, $00, $00);
+ Nop4: array [0 .. 3] of Byte = ($0F, $1F, $40, $00);
+ Nop3: array [0 .. 2] of Byte = ($0F, $1F, $00);
+ Nop2: array [0 .. 1] of Byte = ($66, $90);
+ Nop1: array [0 .. 0] of Byte = ($90);
+ MultiNops: array [0 .. 8] of PByte = ( //
+ @Nop1, { Standard Nop }
+ @Nop2, { 2 Bytes Nop }
+ @Nop3, { 3 Bytes Nop }
+ @Nop4, { 4 Bytes Nop }
+ @Nop5, { 5 Bytes Nop }
+ @Nop6, { 6 Bytes Nop }
+ @Nop7, { 7 Bytes Nop }
+ @Nop8, { 8 Bytes Nop }
+ @Nop9 { 9 Bytes Nop }
+
+ );
+
+function IsMultiBytesNop(const P: PByte; Len: ShortInt = 0): Boolean;
+var
+ i: Integer;
+ nL: Integer;
+begin
+ for i := Length(MultiNops) downto 1 do
+ begin
+ nL := i;
+ Result := CompareMem(MultiNops[i - 1], P, nL);
+ if Result then
+ begin
+ if Len < 0 then
+ Exit;
+ Result := (nL = Len);
+ if Result then
+ Exit;
+ end;
+ end;
+end;
+
+procedure FillMultiNop(var Buff; Size: Integer);
+var
+ i: Integer;
+ nL: Byte;
+ P: PByte;
+begin
+ { Multi Bytes Nop Instructions seems to be
+ faster to execute rather than
+ the traditional (NOP x n) instructions.
+
+ However it's not supported by all CPU !
+ ==> Use FillNop(P,Size,True)!
+
+ ==> CPUID implement a routine to detect
+ if the CPU support Multi Bytes Nop .
+ }
+ if not(iMultiNop in CPUInsts) then
+ raise InterceptException.Create(ErrMultiNopNotSup);
+
+ P := PByte(@Buff);
+ for i := Length(MultiNops) downto 1 do
+ begin
+ nL := i;
+ if Size = 0 then
+ Break;
+ while Size >= nL do
+ begin
+ Move(MultiNops[i - 1]^, P^, nL);
+ Dec(Size, nL);
+ Inc(P, nL);
+ end;
+ end;
+end;
+{$ENDIF UseMultiBytesNop}
+
+function IsNop(const P: PByte; Len: ShortInt; MultiBytesNop: Boolean = False): Boolean;
+var
+ i: Integer;
+ Q: PByte;
+begin
+ { Return True if the first instructions are nop/multi nop ! }
+ Result := False;
+ Q := P;
+{$IFDEF UseMultiBytesNop}
+ if (MultiBytesNop and (iMultiNop in CPUInsts)) then
+ Result := IsMultiBytesNop(P, Len)
+ else
+{$ENDIF UseMultiBytesNop}
+ for i := 0 to Len - 1 do
+ begin
+ Result := (Q^ = opNop);
+ if not Result then
+ Exit;
+ Inc(Q); // Next Byte.
+ end;
+end;
+
+procedure FillNop(var P; const Size: Integer; const MultiBytesNop: Boolean = False); {$IFDEF MustInline}inline; {$ENDIF}
+begin
+{$IFDEF UseMultiBytesNop}
+ if (MultiBytesNop and (iMultiNop in CPUInsts)) then
+ FillMultiNop(P, Size)
+ else
+{$ENDIF UseMultiBytesNop}
+ FillChar(PByte(@P)^, Size, opNop);
+end;
+
+function GetPrefixesCount(Prefixes: WORD): Byte;
+var
+ Prf: WORD;
+ i: Byte;
+begin
+ { Get prefixes count used by the instruction. }
+ Result := 0;
+ if Prefixes = 0 then
+ Exit;
+
+ Prf := 0;
+ i := 0;
+ Prefixes := Prefixes and not Prf_VEX;
+ while Prf < $8000 do
+ begin
+ Prf := (1 shl i);
+ if (Prf and Prefixes = Prf) then
+ Inc(Result);
+ Inc(i);
+ end;
+end;
+
+function GetInstOpCodes(PInst: PInstruction; P: PByte): ShortInt;
+var
+ nPrfs: Byte;
+begin
+ {
+ Return opcodes length
+ Instruction OpCodes in arg P .
+ }
+ Result := 0;
+ FillChar(P^, MAX_INST_LENGTH_N, $90);
+ nPrfs := GetPrefixesCount(PInst^.Prefixes);
+ Inc(Result, nPrfs);
+ case PInst^.OpTable of
+ tbTwoByte:
+ if PInst^.Prefixes and Prf_VEX3 = 0 then
+ Inc(Result); // $0F
+ tbThreeByte:
+ begin
+ if PInst^.Prefixes and Prf_VEX3 = 0 then
+ Inc(Result, 2); // 0F + 38|3A !
+ end;
+ tbFPU: Inc(Result, 2); // [$D8..$D9] + ModRm !
+ end;
+ if PInst^.Prefixes and Prf_Vex2 <> 0 then
+ Inc(Result); // VEX.P0
+ if PInst^.Prefixes and Prf_VEX3 <> 0 then
+ Inc(Result, 2); // VEX.P0 + VEX.P1
+ if PInst^.OpKind = kGrp then
+ Inc(Result, 2) // Group + ModRm
+ else
+ Inc(Result); // OpCode
+ if Assigned(P) then
+ Move(PInst^.Addr^, P^, Result);
+end;
+
+function CorrectJ(PInst: PInstruction; NewAddr: PByte): Integer;
+const
+ { Convert LOOP instruction to relative word jcc ! }
+ LOOP_To_JccZ: array [0 .. 3] of WORD = ($850F, $840F, $840F, $9090);
+ { Convert LOOP instruction to relative byte jcc ! }
+ LOOP_To_JccB: array [0 .. 3] of Byte = ($75, $74, $75, $90);
+var
+ Offset: Int64;
+ POpc: PByte;
+ // Opcsz: Integer;
+ NOpc: DWORD;
+ PQ: PByte;
+ Relsz: Byte;
+ JmpType: Byte;
+ JmpSize: Byte;
+ function GetJccOpCode(RelSize: Byte): DWORD;
+ var
+ LOp: Byte;
+ Opc: array [0 .. 3] of Byte;
+ begin
+ FillChar(PByte(@Opc[0])^, 4, #0);
+ LOp := PInst^.OpCode and $F;
+ case RelSize of
+ ops8bits:
+ begin
+ Opc[0] := $70 or LOp;
+ end;
+ ops16bits:
+ begin
+ Opc[0] := opPrfOpSize;
+ Opc[1] := $0F;
+ Opc[2] := $80 or LOp;
+ end;
+ ops32bits:
+ begin
+ Opc[0] := $0F;
+ Opc[1] := $80 or LOp;
+ end;
+ end;
+ Result := PDWORD(@Opc[0])^;
+ end;
+
+begin
+ PQ := NewAddr;
+ JmpSize := 0;
+ GetMem(POpc, MAX_INST_LENGTH_N + 1);
+ try
+ // Opcsz := GetInstOpCodes(PInst, POpc);
+ Offset := Int64(UInt64(PInst^.Branch.Target) - UInt64(PQ) - 6);
+ Relsz := GetInt64Size(Offset);
+{$IFDEF CPUX64}
+ if Relsz = ops16bits then
+ Relsz := ops32bits;
+{$ENDIF CPUX64}
+ if PInst^.OpType and otJcc = 0 then
+ begin
+ { Not Jcc ! }
+ if PInst^.OpCode in [$E0 .. $E2] then
+ begin
+ { LOOPNE/LOOPZ/LOOP }
+ if Relsz = ops8bits then
+ begin
+ if PInst^.Prefixes and Prf_AddrSize <> 0 then
+ begin
+ PQ^ := opPrfAddrSize;
+ Inc(PQ);
+ end;
+ PQ^ := PInst^.OpCode;
+ Inc(PQ);
+ PQ^ := Int8(Offset);
+ Inc(PQ);
+ end
+ else
+ case PInst^.AddrMode of
+ am16:
+ begin
+ { Dec CX ! }
+{$IFDEF CPUX64}
+ { . $49 result in REX
+ ==> Use $FF group !
+ }
+ PQ^ := opPrfOpSize;
+ Inc(PQ);
+ PQ^ := $FF;
+ Inc(PQ);
+ PQ^ := $C9;
+ Inc(PQ);
+{$ELSE !CPUX64}
+ PQ^ := opPrfOpSize;
+ Inc(PQ);
+ PQ^ := $49;
+ Inc(PQ);
+{$ENDIF CPUX64}
+ end;
+ am32:
+ begin
+ { Dec ECX ! }
+{$IFDEF CPUX64}
+ PQ^ := $FF;
+ Inc(PQ);
+ PQ^ := $C9;
+ Inc(PQ);
+{$ELSE !CPUX64}
+ PQ^ := $49;
+ Inc(PQ);
+{$ENDIF CPUX64}
+ end;
+ am64:
+ begin
+ { Dec RCX ! }
+ PQ^ := $48; // REX.W = True !
+ Inc(PQ);
+ PQ^ := $FF;
+ Inc(PQ);
+ PQ^ := $C9;
+ Inc(PQ);
+ end;
+ end;
+ case Relsz of
+ ops16bits:
+ begin
+ Offset := Int64(UInt64(PInst^.Branch.Target) - UInt64(PQ) - 5);
+ PQ^ := opPrfOpSize;
+ Inc(PQ);
+ PWord(PQ)^ := LOOP_To_JccZ[PInst^.OpCode and 3];
+ Inc(PQ, 2);
+ PInt16(PQ)^ := Int16(Offset);
+ Inc(PQ, 2);
+ end;
+ ops32bits:
+ begin
+ Offset := Int64(UInt64(PInst^.Branch.Target) - UInt64(PQ) - 6);
+ PWord(PQ)^ := LOOP_To_JccZ[PInst^.OpCode and 3];
+ Inc(PQ, 2);
+ PInt32(PQ)^ := Int32(Offset);
+ Inc(PQ, 4);
+ end;
+ ops64bits:
+ begin
+ {
+ Dec RCX
+ Jcc @Tmp
+ Jmp @NextInst
+ @Tmp:
+ Jmp @LoopDst
+ }
+ { Insert Jcc ! }
+ PQ^ := LOOP_To_JccB[PInst^.OpCode and 3];
+ Inc(PQ);
+ PQ^ := 2;
+ Inc(PQ);
+ { Insert Jmp NextInst }
+ PQ^ := opJmpRelb;
+ Inc(PQ);
+ PQ^ := 14;
+ Inc(PQ);
+ { Insert Jmp @LoopDst }
+ InsertJmp(PQ, PInst.Branch.Target, tJmpRipZ);
+ Inc(PQ, 14);
+ end;
+ end;
+ end
+ else if PInst^.OpCode = $E3 then
+ begin
+ { JCXZ/JECX/JRCX }
+ if Relsz = ops8bits then
+ begin
+ if PInst^.Prefixes and Prf_AddrSize <> 0 then
+ begin
+ PQ^ := opPrfAddrSize;
+ Inc(PQ);
+ end;
+ PQ^ := PInst^.OpCode;
+ Inc(PQ);
+ PQ^ := Int8(Offset);
+ Inc(PQ);
+ end
+ else
+ case PInst^.AddrMode of
+ am16:
+ begin
+ { TEST CX,CX }
+ PQ^ := opPrfOpSize;
+ Inc(PQ);
+ PQ^ := opTestb;
+ Inc(PQ);
+ PQ^ := $C9; // ModRm [Mod = 3; Reg = Rm = CX = 1]
+ Inc(PQ);
+ end;
+ am32:
+ begin
+ { TEST ECX,ECX }
+ PQ^ := opTestb;
+ Inc(PQ);
+ PQ^ := $C9;
+ Inc(PQ);
+ end;
+ am64:
+ begin
+ { TEST RCX,RCX }
+ PQ^ := $48; // REX.W = True !
+ Inc(PQ);
+ PQ^ := opTestb;
+ Inc(PQ);
+ PQ^ := $C9;
+ Inc(PQ);
+ end;
+ end;
+ case Relsz of
+ ops16bits:
+ begin
+ {
+ TEST CX,CX
+ JZ @Dst
+ }
+ Offset := Int64(UInt64(PInst^.Branch.Target) - UInt64(PQ) - 5);
+ PQ^ := opPrfOpSize;
+ Inc(PQ);
+ PQ^ := $0F;
+ Inc(PQ);
+ PQ^ := $84; // JZ !
+ Inc(PQ);
+ PInt16(PQ)^ := Int16(Offset);
+ Inc(PQ, 2);
+ end;
+ ops32bits:
+ begin
+ {
+ TEST ECX,ECX
+ JZ @Dst
+ }
+ Offset := Int64(UInt64(PInst^.Branch.Target) - UInt64(PQ) - 6);
+ PQ^ := $0F;
+ Inc(PQ);
+ PQ^ := $84; // JZ !
+ Inc(PQ);
+ PInt32(PQ)^ := Int32(Offset);
+ Inc(PQ, 4);
+ end;
+ ops64bits:
+ begin
+ {
+ TEST RCX,RCX
+ JZ @Tmp
+ Jmp @NextInst
+ @Tmp:
+ Jmp @Dst
+ }
+ { Insert JZ ! }
+ PQ^ := $74;
+ Inc(PQ);
+ PQ^ := 2;
+ Inc(PQ);
+ { Insert Jmp NextInst }
+ PQ^ := opJmpRelb;
+ Inc(PQ);
+ PQ^ := 14;
+ Inc(PQ);
+ { Insert Jmp @Dst }
+ InsertJmp(PQ, PInst.Branch.Target, tJmpRipZ);
+ Inc(PQ, 14);
+ end;
+ end;
+ end;
+ end else begin
+ { Jcc ! }
+ NOpc := GetJccOpCode(Relsz);
+ case Relsz of
+ ops8bits:
+ begin
+ Offset := Int64(UInt64(PInst^.Branch.Target) - UInt64(PQ) - 2);
+ PInt8(PQ)^ := UInt8(NOpc);
+ Inc(PQ);
+ PInt8(PQ)^ := Int8(Offset);
+ Inc(PQ);
+ end;
+ ops16bits:
+ begin
+ Offset := Int64(UInt64(PInst^.Branch.Target) - UInt64(PQ) - 5);
+ PUInt32(PQ)^ := UInt32(NOpc);
+ Inc(PQ, 3);
+ PInt16(PQ)^ := Int16(Offset);
+ Inc(PQ, 2);
+ end;
+ ops32bits:
+ begin
+ Offset := Int64(UInt64(PInst^.Branch.Target) - UInt64(PQ) - 6);
+ PUInt16(PQ)^ := UInt16(NOpc);
+ Inc(PQ, 2);
+ PInt32(PQ)^ := Int32(Offset);
+ Inc(PQ, 4);
+ end;
+ ops64bits:
+ begin
+ {
+ Unfortunately there is no Jcc Rel 64bits !
+
+ ===>Original implementation<===
+ test eax,eax
+ jz @DstAddr
+
+ ===>New implementation<===
+ test eax,eax
+ Q: jz @tmp
+ Q+2: jmp @NextInst
+ Q+4: @tmp:
+ Q+4: jmp @DstAddr
+ Q+4+jmpsize: [DstAddr]
+ @NextInstruction:
+ }
+
+ { jz @tmp is guaranteed to be 2 Bytes in length ! }
+ { Trampo.NextInstruction = Q + 4 + jmp @DstAddr Size }
+ PQ^ := PInst^.OpCode;
+ Inc(PQ);
+ PQ^ := 2;
+ Inc(PQ);
+ JmpType := GetJmpType(NewAddr + 4, PInst^.Branch.Target, NewAddr + 4 + 6);
+ JmpSize := JmpTypeToSize[JmpSize];
+ if JmpType > tJmpRel32 then
+ Inc(JmpSize, SizeOf(Pointer));
+
+ { Jmp To Next Valid Instruction ! }
+ PQ^ := opJmpRelb;
+ Inc(PQ);
+ PQ^ := JmpSize;
+ Inc(PQ);
+
+ InsertJmp(NewAddr + 4, PInst^.Branch.Target, JmpType, NewAddr + 4 + 6);
+ Inc(PQ, JmpSize);
+ end;
+ end;
+ end;
+ finally
+ FreeMem(POpc);
+ end;
+ Result := PQ - NewAddr;
+ if Result = 00 then
+ begin
+ Move(PInst^.Addr^, NewAddr^, PInst^.InstSize);
+ Result := PInst^.InstSize;
+ end;
+end;
+
+function MakeModRm(iMod, Reg, Rm: Byte): Byte; {$IFDEF MustInline}inline; {$ENDIF}
+begin
+ Result := (iMod shl 6) or (Reg shl 3) or (Rm);
+end;
+
+function CorrectRipDisp(PInst: PInstruction; NewAddr: PByte): Integer;
+type
+ PNativeUInt = ^NativeUInt;
+var
+ Offset: Int64;
+ P: PByte;
+ rReg: Byte;
+ POpc: PByte;
+ pMR: PByte;
+ pFrst: PByte;
+ L: ShortInt;
+begin
+ pFrst := NewAddr;
+ P := PInst^.NextInst;
+ {
+ If AddressMode is 32-bits :
+ ===> EIP + Disp32 !
+ else
+ If AddressMode is 64-bits:
+ ===> RIP + Disp32 !
+ }
+ if PInst^.AddrMode = am32 then
+ P := PByte(UInt64(P) and $FFFFFFFF);
+
+ P := P + Int64(PInst^.Disp.Value);
+
+ Offset := Int64(UInt64(P) - UInt64(NewAddr) - PInst^.InstSize);
+ if Int32(Offset) <> Offset then
+ begin
+ rReg := rEAX;
+ if PInst^.ModRm.Flags and mfUsed <> 0 then
+ begin
+ Assert(PInst^.Disp.Flags and dfRip <> 0);
+ if PInst^.ModRm.Reg = rReg then
+ rReg := rECX;
+
+ { PUSH UsedReg }
+ PByte(NewAddr)^ := $50 + (rReg and $7);
+ Inc(NewAddr);
+
+{$IFDEF CPUX64}
+ PByte(NewAddr)^ := $48; // REX.W!
+ Inc(NewAddr);
+{$ENDIF CPUX64}
+ { MOV REG,Imm(NativeUInt) }
+ PByte(NewAddr)^ := $B8 + (rReg and $7);
+ Inc(NewAddr);
+ PNativeUInt(NewAddr)^ := NativeUInt(P);
+ Inc(NewAddr, SizeOf(NativeUInt));
+
+ { Set the original instruction opcodes }
+ POpc := GetMemory(MAX_INST_LENGTH_N);
+ L := GetInstOpCodes(PInst, POpc);
+
+ Move(PByte(@POpc[0])^, NewAddr^, L);
+ Inc(NewAddr, L);
+ pMR := NewAddr;
+ if (PInst^.OpKind and kGrp <> 0) or (PInst^.OpTable = tbFPU) then
+ Dec(pMR);
+
+ PByte(pMR)^ := MakeModRm($00, PInst^.ModRm.Reg, rReg);
+ Inc(pMR);
+ NewAddr := pMR;
+
+ { POP UsedReg }
+ PByte(NewAddr)^ := $58 + (rReg and $7);
+ Inc(NewAddr);
+
+ FreeMemory(POpc);
+ Exit(NewAddr - pFrst);
+ end
+ else
+ raise InterceptException.Create(ErrRipDisp);
+ end;
+ Move(PInst^.Addr^, NewAddr^, PInst^.InstSize);
+ Inc(NewAddr, PInst^.InstSize);
+ PInt32(NewAddr - SizeOf(Int32))^ := Int32(Offset);
+
+ Result := PInst^.InstSize;
+end;
+
+function CorrectJmpRel(PInst: PInstruction; NewAddr: PByte): Integer;
+var
+ JmpType: Byte;
+begin
+ JmpType := GetJmpType(NewAddr, PInst^.Branch.Target, NewAddr + 6);
+ InsertJmp(NewAddr, PInst^.Branch.Target, JmpType, NewAddr + 6);
+ Result := JmpTypeToSize[JmpType];
+end;
+
+function CorrectCallRel(PInst: PInstruction; NewAddr: PByte): Integer;
+var
+ Offset: Int64;
+ Relsz: Byte;
+ P: PByte;
+begin
+ P := NewAddr;
+ Offset := Int64(UInt64(PInst^.Branch.Target) - UInt64(P) - 6);
+ Relsz := GetInt64Size(Offset);
+{$IFDEF CPUX64}
+ { Only 32-bits relative offset is supported on x64! }
+ if Relsz < ops32bits then
+ Relsz := ops32bits;
+{$ELSE !CPUX64}
+ { Only 16/32-bits relative offset is supported on x32! }
+ if Relsz < ops16bits then
+ Relsz := ops32bits;
+{$ENDIF CPUX64}
+ case Relsz of
+ ops16bits:
+ begin
+ Offset := Int64(UInt64(PInst^.Branch.Target) - UInt64(P) - 4);
+ P^ := opPrfOpSize;
+ Inc(P);
+ P^ := $E8;
+ Inc(P);
+ PInt16(P)^ := Int16(Offset);
+ Inc(P, 2);
+ end;
+ ops32bits:
+ begin
+ Offset := Int64(UInt64(PInst^.Branch.Target) - UInt64(P) - 5);
+ P^ := $E8;
+ Inc(P);
+ PInt32(P)^ := Int32(Offset);
+ Inc(P, 4);
+ end;
+ ops64bits:
+ begin
+ {
+ 64-bits Relative offset is not supported
+ ==> Map to a new opcode !
+ }
+ {
+ CALL [02]
+ Jmp @NextValidInstruction
+ dq : Call dst address !
+ @NextValidInstruction:
+
+ }
+ P^ := $FF; // Group 5 !
+ Inc(P);
+ {
+ ModRm.Mod = 00
+ ModRm.Reg = 02
+ ModRm.Rm = 05
+ ==> ModRm = $15 !
+ }
+ P^ := MakeModRm($00, $02, $05);
+ Inc(P);
+ P^ := 2;
+ Inc(P, 4);
+
+ { Jmp Next Instruction ! }
+ P^ := opJmpRelb;
+ Inc(P);
+ P^ := $08;
+ Inc(P);
+ PUInt64(P)^ := UInt64(PInst^.Branch.Target);
+ Inc(P, SizeOf(UInt64));
+ end;
+ end;
+ Result := P - NewAddr;
+ if Result = 0 then
+ begin
+ Move(PInst^.Addr^, P^, PInst^.InstSize);
+ Result := PInst^.InstSize;
+ end;
+end;
+
+function MapInsts(Addr, NewAddr: PByte; Size: Integer): Integer;
+var
+ P, Q: PByte;
+ PInst: PInstruction;
+ sz, iz, nz: Integer;
+begin
+ { Map Data from Addr to NewAddr ! }
+ { This function will fix Relative offset & RIP displacement . }
+ Result := 0;
+ sz := 0;
+ P := Addr;
+ Q := NewAddr;
+ PInst := GetMemory(SizeOf(TInstruction));
+ FillChar(PInst^, SizeOf(TInstruction), #0);
+
+ PInst^.Archi := CPUX;
+ PInst^.NextInst := P;
+ PInst^.VirtualAddr := nil;
+
+ while sz < Size do
+ begin
+ PInst^.Addr := PInst^.NextInst;
+ iz := fDecodeInst(PInst);
+ nz := iz;
+ if PInst^.Disp.Flags and (dfUsed or dfRip) = (dfUsed or dfRip) then
+ nz := CorrectRipDisp(PInst, Q)
+ else if (PInst^.Branch.Falgs and bfRel = bfRel) then
+ begin
+ { Instruction use relative offset }
+ if (PInst^.OpType = otJMP) then
+ nz := CorrectJmpRel(PInst, Q)
+ else if (PInst^.OpType = otCALL) then
+ nz := CorrectCallRel(PInst, Q)
+ else
+ nz := CorrectJ(PInst, Q)
+ end
+ else
+ Move(PInst^.Addr^, Q^, nz);
+ Inc(Q, nz);
+ Inc(Result, nz);
+ Inc(sz, iz);
+ end;
+ FreeMemory(PInst);
+end;
+
+const
+ arNone = $00;
+ arPlus = $08;
+ arMin = $10;
+ arAdd = arPlus or $01;
+ arSub = arMin or $01;
+ arInc = arPlus or $02;
+ arDec = arMin or $02;
+
+{$WARN COMPARISON_TRUE OFF}
+
+function GetInstArithmeticType(PInst: PInstruction): Byte;
+ function IsInstAdd(PInst: PInstruction): Boolean;
+ begin
+ Result := False;
+ if PInst^.OpTable = tbOneByte then
+ begin
+ if (PInst^.OpCode >= $00) and (PInst^.OpCode < $06) then
+ Exit(True);
+ end;
+ if (PInst^.OpKind = kGrp) and (PInst^.ModRm.Reg = $00) then
+ begin
+ if (PInst^.OpCode > $7F) and (PInst^.OpCode < $84) then
+ Exit(True);
+ end;
+ end;
+ function IsInstSub(PInst: PInstruction): Boolean;
+ begin
+ Result := False;
+ if PInst^.OpTable = tbOneByte then
+ begin
+ if (PInst^.OpCode > $27) and (PInst^.OpCode < $2E) then
+ Exit(True);
+ end;
+ if (PInst^.OpKind = kGrp) and (PInst^.ModRm.Reg = $05) then
+ begin
+ if (PInst^.OpCode > $7F) and (PInst^.OpCode < $84) then
+ Exit(True);
+ end;
+ end;
+ function IsInstInc(PInst: PInstruction): Boolean;
+ begin
+ Result := False;
+ if (PInst^.Archi = CPUX32) and (PInst^.OpTable = tbOneByte) then
+ begin
+ if (PInst^.OpCode >= $40) and (PInst^.OpCode <= $47) then
+ Exit(True);
+ end;
+ if (PInst^.OpKind = kGrp) and (PInst^.ModRm.Reg = $00) then
+ begin
+ if (PInst^.OpCode = $FE) or (PInst^.OpCode = $FF) then
+ Exit(True);
+ end;
+ end;
+ function IsInstDec(PInst: PInstruction): Boolean;
+ begin
+ Result := False;
+ if (PInst^.Archi = CPUX32) and (PInst^.OpTable = tbOneByte) then
+ begin
+ if (PInst^.OpCode >= $48) and (PInst^.OpCode <= $4F) then
+ Exit(True);
+ end;
+ if (PInst^.OpKind = kGrp) and (PInst^.ModRm.Reg = $01) then
+ begin
+ if (PInst^.OpCode = $FE) or (PInst^.OpCode = $FF) then
+ Exit(True);
+ end;
+ end;
+
+begin
+ { Return Instruction Arithmetic (+ or - or ..) }
+ Result := arNone;
+ if IsInstAdd(PInst) then
+ Exit(arAdd);
+ if IsInstInc(PInst) then
+ Exit(arAdd);
+ if IsInstSub(PInst) then
+ Exit(arSub);
+ if IsInstDec(PInst) then
+ Exit(arSub);
+end;
+{$WARN COMPARISON_TRUE ON}
+
+function EvalArithU(Arith: Byte; Value: NativeUInt; Offset: NativeInt): NativeUInt;
+begin
+ Result := Value;
+ case Arith of
+ arAdd: Inc(Result, Offset);
+ arInc: Inc(Result);
+ arSub: Dec(Result, Offset);
+ arDec: Dec(Result);
+ end;
+end;
+
+{$HINTS OFF}
+
+function InterfaceToObj(const AIntf): TObject;
+const
+ {
+ Delphi insert QueryInterface,_AddRef,_Release methods
+ as the last functions in the code entry.
+ => We must skip them to point to the first function declared in the interface.
+ }
+ Offset = SizeOf(Pointer) * 3;
+{$IFDEF CPUX64}
+ ObjReg = rECX;
+{$ELSE !CPUX64}
+ ObjReg = rEAX;
+{$ENDIF CPUX64}
+var
+ Pvt, PCode: PByte;
+ Inst: TInstruction;
+ PObj: PByte;
+ imm: Int64;
+ Arith: Byte;
+ Skip: Boolean;
+ sReg: ShortInt;
+begin
+
+ if not Assigned(@AIntf) then
+ Exit(nil);
+
+ sReg := -1;
+ PObj := PByte(AIntf);
+{$IFNDEF FPC}
+ Inst := default (TInstruction);
+{$ENDIF !FPC}
+ Inst.Archi := CPUX;
+ Pvt := PPointer(AIntf)^; // vTable !
+ PCode := PPointer(Pvt + Offset)^; // Code Entry !
+ Inst.NextInst := PCode;
+ {
+ At the top of code entry delphi will generate :
+ int 3
+ add/sub eax/rcx,offset <===
+ jmp FirstFunction
+ }
+
+ while True do
+ begin
+ Inst.imm.Value := 0;
+ Inst.Addr := Inst.NextInst;
+ fDecodeInst(@Inst);
+ { Keep looping until JMP/RET ! }
+ if (Inst.Branch.Falgs and bfUsed <> 0) or (Inst.OpType = otRET) then
+ Break;
+
+ Arith := GetInstArithmeticType(@Inst);
+ Skip := (Arith = arNone);
+
+ if not Skip then
+ begin
+{$IFDEF CPUX86}
+ if Inst.ModRm.iMod <> $03 then
+ begin
+ {
+ ====> stdcall ! <====
+ If the method (declared in interface)
+ calling convention is stdcall,
+ Delphi will generate :
+ add/sub [esp+offset],imm !
+ }
+ if Inst.Sib.Flags and sfUsed <> 0 then
+ sReg := Inst.Sib.Index
+ else
+ sReg := Inst.ModRm.Rm;
+ Skip := not(sReg = rESP);
+ end
+ else
+{$ENDIF CPUX86}
+ begin
+ if (Inst.ModRm.Flags and mfUsed <> 0) then
+ Skip := not((Inst.ModRm.iMod = $03) and (Inst.ModRm.Rm = ObjReg))
+ else if Arith in [arInc, arDec] then
+ { Is Inc/Dec EAX/RCX ? }
+ Skip := (Inst.OpCode and $07 <> ObjReg);
+ end;
+ end;
+
+ if not Skip then
+ begin
+ imm := Inst.imm.Value;
+ PObj := PByte(EvalArithU(Arith, NativeUInt(PObj), imm));
+ end;
+ end;
+
+ Result := TObject(PObj);
+end;
+
+{$HINTS ON}
+
+function GetInterfaceMethodPtrByIndex(const PInterface; MethodIndex: Integer): PByte;
+var
+ Pvt: PPointer;
+ P: PPointer;
+ PDst: PByte;
+ Inst: TInstruction;
+ i: Integer;
+begin
+ {
+ Return original method ptr
+ => Return first instruction that was
+ implemented on Interface object !
+ }
+{$IFNDEF FPC}
+ Inst := default (TInstruction);
+{$ENDIF !FPC}
+ Inst.Archi := CPUX;
+ Pvt := PPointer(PInterface)^; // Virtual Table !
+ P := Pvt;
+ // Inc(PByte(P), MethodIndex * SizeOf(NativeUInt));
+ Inc(P, MethodIndex);
+ P := PPointer(P)^;
+ PDst := PByte(P);
+ Inst.NextInst := PByte(P);
+ for i := 0 to 3 do
+ begin
+ Inst.Addr := Inst.NextInst;
+ fDecodeInst(@Inst);
+ if Assigned(Inst.Branch.Target) then
+ begin
+ PDst := Inst.Branch.Target;
+ Break;
+ end;
+ end;
+ Result := PDst;
+end;
+
+{$IFDEF MustUseGenerics}
+
+function GetMethodPtrFromObjByName(Obj: TObject; const MethodName: String): Pointer;
+var
+ LCtx: TRttiContext;
+ LType: TRttiType;
+ LMethods: TArray;
+ LMethod: TRttiMethod;
+begin
+ Result := nil;
+ if (not Assigned(Obj)) or (MethodName = EmptyStr) then
+ Exit;
+
+ LCtx := TRttiContext.Create;
+ LType := LCtx.GetType(Obj.ClassType);
+ LMethods := LType.GetMethods;
+ for LMethod in LMethods do
+ begin
+ if SameText(LMethod.Name, MethodName) then
+ Exit(LMethod.CodeAddress);
+ end;
+end;
+
+function GetInterfaceMethodPtrByName(const PInterface; const MethodName: String): PByte;
+var
+ Obj: TObject;
+begin
+ Result := nil;
+ if (not Assigned(@PInterface)) or (MethodName = EmptyStr) then
+ Exit;
+ Obj := InterfaceToObj(PInterface);
+ if Assigned(Obj) then
+ begin
+ Result := GetMethodPtrFromObjByName(Obj, MethodName);
+ end;
+end;
+
+var
+ GlobalThreadList: TDictionary;
+
+{$ENDIF MustUseGenerics}
+ { TIntercept }
+
+constructor TIntercept.Create(Options: Byte);
+begin
+ FOptions := Options;
+ FList := nil;
+
+ if (FOptions and ST = ST)
+{$IFDEF MustUseGenerics}
+ and (not GlobalThreadList.ContainsKey(GetCurrentThread))
+{$ENDIF MustUseGenerics}
+ then
+ begin
+ { Suspend All threads ! }
+ if OpenThreadExist then
+ begin
+ FList := TThreadsIDList.Create;
+ SuspendAllThreads(FList);
+ end;
+ end;
+
+ if not Assigned(FList) then
+ begin
+ TInterceptMonitor.Enter();
+ end;
+end;
+
+destructor TIntercept.Destroy;
+begin
+ if Assigned(FList) then
+ begin
+ ResumeSuspendedThreads(FList);
+ FreeAndNil(FList);
+ end else begin
+ TInterceptMonitor.Leave();
+ end;
+ inherited;
+end;
+
+function TIntercept.GetDescriptor(P: PByte): PDescriptor;
+var
+ Inst: TInstruction;
+ function IsDscrpInst(PInst: PInstruction): Boolean;
+ begin
+ Result :=
+{$IFDEF UseMultiBytesNop}
+ (IsNop(PInst.Addr, 6, True)) or
+{$ELSE !UseMultiBytesNop}
+ (IsNop(PInst.Addr, 6)) or
+{$ENDIF UseMultiBytesNop}
+ (Assigned(PInst.Branch.Target));
+ end;
+
+begin
+ Result := nil;
+{$IFNDEF FPC}
+ Inst := default (TInstruction);
+{$ENDIF !FPC}
+ Inst.Archi := CPUX;
+ Inst.VirtualAddr := nil;
+ { Find last JMP ! }
+ P := GetRoot(P);
+ Inst.Addr := P;
+ fDecodeInst(@Inst);
+
+ { The first instruction must be NOP ! }
+ if Inst.OpCode = opNop then
+ begin
+ Inst.Addr := Inst.NextInst;
+ fDecodeInst(@Inst);
+ if IsDscrpInst(@Inst) then
+ begin
+ Inc(P); // Skip CodeEntry !
+ Inc(P, SizeOf(TJmpMem) * (MAX_HOOKS + 1)); // Skip JmpMems !
+ { Go to the Top ! }
+ Dec(P, SizeOf(TDescriptor));
+ if IsValidDescriptor(P) then
+ Result := PDescriptor(P);
+ end;
+ end;
+end;
+
+class function TIntercept.GetRoot(P: PByte): PByte;
+var
+ Inst: TInstruction;
+begin
+ Result := P;
+{$IFNDEF FPC}
+ Inst := default (TInstruction);
+{$ENDIF !FPC}
+ Inst.Addr := P;
+ Inst.Archi := CPUX;
+ Inst.VirtualAddr := nil;
+ {
+ While the opcode is jmp and the jmp destination
+ address is known get the next jmp .
+ }
+ fDecodeInst(@Inst);
+ if (Inst.OpType = otJMP) and (Assigned(Inst.Branch.Target)) then
+ Result := GetRoot(Inst.Branch.Target);
+end;
+
+function TIntercept.CreateNewDescriptor: PDescriptor;
+begin
+ { Create a new descriptor tables ! }
+ Result := AllocMem(SizeOf(TDescriptor));
+ {
+ Hahaha .. this stupid code (between commenet)
+ had take me 2h to figure why my libray does not works !
+ I didn't know what i was thinking in when i wrote this code !
+ :)
+ }
+ // SetMemPermission(Result, SizeOf(TDescriptor), PAGE_READWRITE);
+ // SetMemPermission(@Result^.JmpMems, SizeOf(TJmpMem) * (MAX_HOOKS + 1), PAGE_EXECUTE_READWRITE);
+ FillNop(Result^, SizeOf(TDescriptor));
+ FillNop(Result^.JmpMems[0], SizeOf(TJmpMem) * (MAX_HOOKS + 1), True);
+
+ { A valid descriptor have a valid signature . }
+ CopyMemory(Result, PByte(@DscrSig[0]), DscrSigSize);
+ Result^.nHook := 0;
+ Result^.Flags := 0;
+ Result^.ExMem := nil;
+end;
+
+procedure TIntercept.InsertDescriptor(PAt: PByte; PDscr: PDescriptor);
+const
+ { JMP from Target to Code Entry }
+ kJmpCE = 1;
+ { JMP from Target to Temporal address than JMP to Code Entry }
+ kJmpTmpJmpCE = 2;
+ { JMP from Target to Temporal address than JMP (Rip Zero) to Code Entry }
+ kJmpTmpJmpRipZCE = 3;
+ { JMP (Rip Zero) from Target to Code Entry }
+ kJmpRipZCE = 4;
+
+var
+ fJmpType: Byte; { First JMP }
+{$IFDEF CPUX64}
+ sJmpType: Byte; { Second JMP (if used !) }
+ Tmp: PByte;
+{$ENDIF CPUX64}
+ JmpKind: Byte;
+ P, T: PByte;
+ JmpSize: Byte;
+ Inst: TInstruction;
+ Sb: Byte;
+ OrgAccess: DWORD;
+ Tsz: Integer;
+ PExMem: PByte;
+ LPExMem: PByte;
+begin
+ JmpKind := kJmpCE;
+ Sb := 0;
+ P := PAt;
+ PDscr^.OrgPtr := P;
+ fJmpType := GetJmpType(P, @PDscr^.CodeEntry, @PDscr^.DscrAddr);
+{$IFDEF CPUX64}
+ Tmp := nil;
+ PExMem := TryAllocMemAt(P, SizeOfAlloc, PAGE_EXECUTE_READWRITE);
+{$ELSE !CPUX64}
+ PExMem := TryAllocMemAt(nil, SizeOfAlloc, PAGE_EXECUTE_READWRITE);
+{$ENDIF CPUX64}
+ LPExMem := PExMem;
+{$IFDEF CPUX64}
+ sJmpType := tJmpNone;
+ JmpKind := kJmpRipZCE;
+ { Try to find the perfect jump instruction ! }
+ {
+ That's mean that we try to avoid using tJmpRelN on TargetProc .
+ ==> Because it use more than 6 bytes in length .
+ }
+ if JmpTypeToSize[fJmpType] > 6 then
+ begin
+ Tmp := PExMem;
+ Inc(PExMem, TmpSize);
+ if Assigned(Tmp) then
+ begin
+ JmpKind := kJmpRipZCE;
+ fJmpType := GetJmpType(P, Tmp, Tmp + 6);
+ if JmpTypeToSize[fJmpType] < 7 then
+ begin
+ JmpKind := kJmpTmpJmpRipZCE;
+ sJmpType := GetJmpType(Tmp, @PDscr^.CodeEntry, Tmp + 6 + 8);
+ if JmpTypeToSize[sJmpType] < 7 then
+ JmpKind := kJmpTmpJmpCE;
+ end;
+ end;
+ end else begin
+ JmpKind := kJmpCE;
+ end;
+{$ENDIF CPUX64}
+{$IFNDEF FPC}
+ Inst := default (TInstruction);
+{$ENDIF !FPC}
+ Inst.Archi := CPUX;
+ Inst.NextInst := P;
+ Inst.VirtualAddr := nil;
+
+ JmpSize := JmpTypeToSize[fJmpType];
+
+ while Sb < JmpSize do
+ begin
+ if Inst.OpType = otRET then
+ raise InterceptException.Create(ErrFuncSize);
+ Inst.Addr := Inst.NextInst;
+ Inc(Sb, fDecodeInst(@Inst));
+ end;
+
+ if Sb > TrampoSize then
+ raise InterceptException.Create(ErrTrampoSize);
+
+ { Trampoline momory }
+ T := PExMem;
+ FillNop(T^, TrampoSize);
+
+ PDscr^.Trampo := AllocMem(SizeOf(TTrampoInfo));
+ PDscr^.Trampo^.PData := AllocMem(Sb + 6);
+ FillNop(PDscr^.Trampo^.PData^, Sb + 6);
+ { Save original target routine instruction . }
+ Move(P^, PDscr^.Trampo^.PData^, Sb);
+ PDscr^.Trampo^.Addr := T; // Pointer to the first trampoline instruction.
+ PDscr^.Trampo^.Size := Sb; // Size of stolen instructions .
+
+ Tsz := MapInsts(P, T, Sb);
+ OrgAccess := SetMemPermission(P, Sb, PAGE_EXECUTE_READWRITE);
+ try
+ FillNop(P^, Sb);
+ case JmpKind of
+ kJmpCE:
+ begin
+ { A very good jump ! }
+ {
+ TargetProc :
+ JMP @PDscr^.CodeEntry
+ }
+ InsertJmp(P, @PDscr^.CodeEntry, fJmpType, @PDscr^.DscrAddr);
+ end;
+{$IFDEF CPUX64}
+ kJmpTmpJmpCE:
+ begin
+ {
+ TargetProc :
+ JMP @Tmp ==> Tmp is allocated nearly from TargetProc !
+
+ Tmp:
+ JMP @PDscr^.CodeEntry
+ }
+ InsertJmp(P, Tmp, fJmpType, Tmp + 6);
+ InsertJmp(Tmp, @PDscr^.CodeEntry, sJmpType, Tmp + 6 + 8);
+ end;
+ kJmpTmpJmpRipZCE:
+ begin
+ {
+ TargetProc :
+ JMP @Tmp ==> Tmp is allocated nearly from TargetProc !
+
+ Tmp:
+ JMP @PDscr^.CodeEntry ==> tJmpRipZ
+ }
+ InsertJmp(P, Tmp, fJmpType, Tmp + 6);
+ InsertJmp(Tmp, @PDscr^.CodeEntry, tJmpRipZ, nil);
+ end;
+ kJmpRipZCE:
+ begin
+ {
+ Not a good jump !
+
+ TargetProc :
+ JMP @PDscr^.CodeEntry ==> tJmpRipZ
+ }
+ InsertJmp(P, @PDscr^.CodeEntry, tJmpRipZ, nil);
+ end;
+{$ENDIF CPUX64}
+ end;
+
+ {
+ Insert a JMP instruction after the stolen instructions
+ on the trampoline.
+ ==> This JMP will return to TargetProc to allow
+ executing originals instructions.
+ }
+{$IFDEF CPUX64}
+ // InsertJmp(T + Tsz, P + JmpTypeToSize[fJmpType], tJmpRipZ);
+ InsertJmp(T + Tsz, P + Sb, tJmpRipZ);
+{$ELSE !CPUX64}
+ InsertJmp(T + Tsz, P + Sb, tJmpMem32, T + Tsz + 6);
+{$ENDIF CPUX64}
+ { Save LPExMem ==> we need it when deleting descriptor }
+ PDscr^.ExMem := LPExMem;
+
+ SetMemPermission(LPExMem, SizeOfAlloc, PAGE_EXECUTE_READWRITE);
+ SetMemPermission(PDscr, SizeOf(TDescriptor), PAGE_EXECUTE_READWRITE);
+ finally
+ SetMemPermission(P, Sb, OrgAccess);
+ end;
+end;
+
+function TIntercept.IsValidDescriptor(P: PByte): Boolean;
+begin
+ Result := CompareMem(P, PByte(@DscrSig[0]), SizeOf(DscrSig));
+end;
+
+function TIntercept.AddHook(PDscr: PDescriptor; InterceptProc: PByte; const Options: Byte): PByte;
+var
+ n: ShortInt;
+ NxHook: PByte;
+begin
+ {
+ Return a pointer to a function that can
+ call next installed Hooks.
+ }
+ n := PDscr^.nHook;
+ if n + 1 > MAX_HOOKS then
+ raise InterceptException.Create(ErrMaxHook);
+
+ { Alloc memory for the NextHook ! }
+ NxHook := AllocMem(TrampoSize);
+ Result := NxHook;
+
+ FillNop(Result^, TrampoSize);
+
+ PNextHook(Result)^.PDscr := PDscr;
+ PNextHook(Result)^.ID := n + 1;
+ Inc(Result, SizeOf(TNextHook));
+
+ { Redirect code to InterceptProc ! }
+ InsertJmp(@PDscr^.JmpMems[n], InterceptProc, tJmpMemN, @PDscr^.JmpAddrs[n]);
+ { Redirect code to TrampoLine ! }
+ InsertJmp(@PDscr^.JmpMems[n + 1], PDscr^.Trampo^.Addr, tJmpMemN, @PDscr^.JmpAddrs[n + 1]);
+ { Redirect code to next hook ! }
+ InsertJmp(Result, @PDscr^.JmpMems[n + 1], tJmpMemN, Result + 6);
+ Inc(PDscr^.nHook);
+
+ SetMemPermission(Result, JmpTypeToSize[tJmpRipZ], PAGE_EXECUTE_READWRITE);
+end;
+
+function TIntercept.InstallHook(TargetProc, InterceptProc: PByte; const Options: Byte = $00): PByte;
+var
+ P: PByte;
+ PDscr: PDescriptor;
+begin
+ if not Assigned(TargetProc) then
+ raise InterceptException.Create(ErrTargetProc);
+
+ if not Assigned(InterceptProc) then
+ raise InterceptException.Create(ErrInterceptProc);
+
+ PDscr := GetDescriptor(TargetProc);
+ if not Assigned(PDscr) then
+ begin
+ P := GetRoot(TargetProc);
+ PDscr := CreateNewDescriptor;
+ try
+ InsertDescriptor(P, PDscr);
+ except
+ FreeMem(PDscr);
+ raise;
+ end;
+ end;
+ Result := AddHook(PDscr, InterceptProc);
+end;
+
+procedure TIntercept.RemoveDescriptor(PDscr: PDescriptor);
+var
+ OrgAccess: DWORD;
+ P: PByte;
+ sz: Integer;
+ vr: Boolean;
+begin
+ P := PDscr^.OrgPtr;
+ sz := PDscr^.Trampo^.Size;
+
+ OrgAccess := SetMemPermission(P, sz, PAGE_EXECUTE_READWRITE);
+ try
+ SetMemPermission(PDscr^.ExMem, TrampoSize, PAGE_EXECUTE_READWRITE);
+
+ { Restore the old stolen instructions ! }
+ Move(PDscr^.Trampo^.PData^, PDscr^.OrgPtr^, PDscr^.Trampo^.Size);
+
+ FillNop(PDscr^.ExMem^, SizeOfAlloc);
+ FreeMem(PDscr^.Trampo^.PData);
+ FreeMem(PDscr^.Trampo);
+
+ if Assigned(PDscr^.ExMem) then
+ begin
+ vr := InternalFuncs.VirtualFree(PDscr^.ExMem, 0, MEM_RELEASE);
+ if not vr then
+ RaiseLastOSError;
+ end;
+
+ FillNop(PDscr^, SizeOf(TDescriptor));
+ FreeMem(PDscr);
+ finally
+ SetMemPermission(P, sz, OrgAccess);
+ end;
+end;
+
+function TIntercept.RemoveHook(Trampo: PByte): Integer;
+var
+ PNxtHook: PNextHook;
+ PDscr: PDescriptor;
+ n: Byte;
+begin
+ if not Assigned(Trampo) then
+ raise InterceptException.Create(ErrInvalidTrampo);
+
+ PNxtHook := PNextHook(Trampo - SizeOf(TNextHook));
+ if not Assigned(PNxtHook) then
+ raise InterceptException.Create(ErrInvalidTrampo);
+
+ PDscr := PNxtHook^.PDscr;
+ if not IsValidDescriptor(PByte(PDscr)) then
+ raise InterceptException.Create(ErrInvalidDscr);
+
+ n := PNxtHook^.ID;
+ Dec(PDscr^.nHook);
+
+ PDscr^.JmpAddrs[n - 1] := nil;
+ { Remove JMP from descriptor table }
+ FillNop(PByte(@PDscr^.JmpMems[n - 1])^, SizeOf(TJmpMem), True);
+
+ {
+ Return the number of hooks
+ that are still alive !
+ }
+ Result := PDscr^.nHook;
+
+ if Result = 0 then
+ RemoveDescriptor(PDscr);
+
+ FreeMem(PNxtHook);
+end;
+
+function InterceptCreate(const TargetProc, InterceptProc: Pointer; Options: Byte = v1compatibility): Pointer;
+var
+ Intercept: TIntercept;
+begin
+ Intercept := TIntercept.Create(Options);
+ try
+ Result := Intercept.InstallHook(TargetProc, InterceptProc, Options);
+ finally
+ Intercept.Free;
+ end;
+end;
+
+{ =====> Support for Interface <===== }
+
+function InterceptCreate(const TargetInterface; MethodIndex: Integer; const InterceptProc: Pointer; Options: Byte = v1compatibility): Pointer;
+var
+ P: PByte;
+begin
+ Result := nil;
+ if not Assigned(@TargetInterface) then
+ Exit;
+ P := GetInterfaceMethodPtrByIndex(TargetInterface, MethodIndex);
+ if Assigned(P) then
+ begin
+ Result := InterceptCreate(P, InterceptProc, Options);
+ end;
+end;
+
+{$IFDEF MustUseGenerics}
+
+function InterceptCreate(const TargetInterface; const MethodName: String; const InterceptProc: Pointer; Options: Byte = v1compatibility): Pointer; overload;
+var
+ P: PByte;
+begin
+ Result := nil;
+ if (not Assigned(@TargetInterface)) or (MethodName = EmptyStr) then
+ Exit;
+
+ P := GetInterfaceMethodPtrByName(TargetInterface, MethodName);
+ if Assigned(P) then
+ Result := InterceptCreate(P, InterceptProc, Options);
+end;
+{$ENDIF MustUseGenerics}
+
+function InterceptCreate(const Module, MethodName: string; const InterceptProc: Pointer; ForceLoadModule: Boolean = True;
+ Options: Byte = v1compatibility): Pointer;
+var
+ pOrgPointer: Pointer;
+ LModule: THandle;
+begin
+ { RRUZ's idea ==> Looks great ! }
+ Result := nil;
+ LModule := GetModuleHandle(PChar(Module));
+ if (LModule = 0) and ForceLoadModule then
+ LModule := LoadLibrary(PChar(Module));
+
+ if LModule <> 0 then
+ begin
+ pOrgPointer := GetProcAddress(LModule, PChar(MethodName));
+ if Assigned(pOrgPointer) then
+ Result := InterceptCreate(pOrgPointer, InterceptProc, Options);
+ end;
+end;
+
+procedure InterceptCreate(const TargetProc, InterceptProc: Pointer; var TrampoLine: Pointer; Options: Byte = v1compatibility);
+var
+ Intercept: TIntercept;
+begin
+ Intercept := TIntercept.Create(Options);
+ try
+ TrampoLine := Intercept.InstallHook(TargetProc, InterceptProc, Options);
+ finally
+ Intercept.Free;
+ end;
+end;
+
+function InterceptRemove(const Trampo: Pointer; Options: Byte = v1compatibility): Integer;
+var
+ Intercept: TIntercept;
+begin
+ if not Assigned(Trampo) then
+ Exit(-1);
+ Intercept := TIntercept.Create(Options);
+ try
+ Result := Intercept.RemoveHook(Trampo);
+ finally
+ Intercept.Free;
+ end;
+end;
+
+function GetNHook(const TargetProc: Pointer): ShortInt;
+var
+ Intercept: TIntercept;
+ PDscr: PDescriptor;
+begin
+ {
+ Return the number of installed hooks !
+ Return -1 if no hooks installed !
+ }
+ Result := -1;
+ if not Assigned(TargetProc) then
+ raise InterceptException.Create(ErrTargetProc);
+
+ Intercept := TIntercept.Create(0);
+ try
+ PDscr := Intercept.GetDescriptor(TargetProc);
+ if Assigned(PDscr) then
+ Result := PDscr^.nHook;
+ finally
+ Intercept.Free;
+ end;
+end;
+
+function GetNHook(const TargetInterface; MethodIndex: Integer): ShortInt; overload;
+var
+ P: PByte;
+begin
+ P := GetInterfaceMethodPtrByIndex(TargetInterface, MethodIndex);
+ Result := GetNHook(P);
+end;
+
+{$IFDEF MustUseGenerics }
+
+function GetNHook(const TargetInterface; const MethodName: String): ShortInt; overload;
+var
+ P: PByte;
+begin
+ P := GetInterfaceMethodPtrByName(TargetInterface, MethodName);
+ Result := GetNHook(P);
+end;
+{$ENDIF MustUseGenerics }
+
+function IsHooked(const TargetProc: Pointer): Boolean;
+begin
+ Result := GetNHook(TargetProc) > 0;
+end;
+
+function IsHooked(const TargetInterface; MethodIndex: Integer): Boolean; overload;
+var
+ P: PByte;
+begin
+ P := GetInterfaceMethodPtrByIndex(TargetInterface, MethodIndex);
+ Result := IsHooked(P);
+end;
+
+{$IFDEF MustUseGenerics }
+
+function IsHooked(const TargetInterface; const MethodName: String): Boolean; overload;
+var
+ P: PByte;
+begin
+ P := GetInterfaceMethodPtrByName(TargetInterface, MethodName);
+ Result := IsHooked(P);
+end;
+{$ENDIF MustUseGenerics }
+
+type
+ TTrampoDataVt = record
+ vAddr: Pointer;
+ Addr: Pointer;
+ end;
+
+ PTrampoDataVt = ^TTrampoDataVt;
+
+function PatchVt(const TargetInterface; MethodIndex: Integer; InterceptProc: Pointer): Pointer;
+var
+ vt: PPointer;
+ P, DstAddr: PPointer;
+ Q: PByte;
+ OrgAccess: DWORD;
+ PInfo: PTrampoDataVt;
+begin
+ {
+ NB: PatchVt does not support multi hook !!
+ PatchVt will patch only vtable !!
+ }
+ Result := nil;
+ if not Assigned(@TargetInterface) then
+ Exit;
+ if not Assigned(InterceptProc) then
+ Exit;
+
+ TInterceptMonitor.Enter;
+ try
+ vt := PPointer(TargetInterface)^;
+ P := vt;
+ Inc(P, MethodIndex);
+ DstAddr := P^; // address !
+
+ OrgAccess := SetMemPermission(P, 32, PAGE_EXECUTE_READWRITE);
+ try
+ P^ := InterceptProc;
+ finally
+ SetMemPermission(P, 32, OrgAccess);
+ end;
+
+ Result := InternalFuncs.VirtualAlloc(nil, 32, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
+ SetMemPermission(Result, 32, PAGE_EXECUTE_READWRITE);
+ PInfo := Result;
+ PInfo^.vAddr := P;
+ PInfo^.Addr := DstAddr;
+ Inc(PByte(Result), SizeOf(TTrampoDataVt));
+
+ Q := Result;
+{$IFDEF CPUX64}
+ { Use JMP RipZero ! }
+ PWord(Q)^ := opJmpMem;
+ Inc(Q, 2);
+ PInt32(Q)^ := $00;
+ Inc(Q, 4);
+ PNativeUInt(Q)^ := NativeUInt(DstAddr);
+{$ELSE !CPUX64}
+ PWord(Q)^ := opJmpMem;
+ Inc(Q, 2);
+ PUInt32(Q)^ := UInt32(Q + 4);
+ PUInt32(Q + 4)^ := UInt32(DstAddr);
+{$ENDIF CPUX64}
+ finally
+ TInterceptMonitor.Leave;
+ end;
+end;
+
+function UnPatchVt(const Trampo: Pointer): Boolean;
+var
+ OrgAccess: DWORD;
+ PInfo: PTrampoDataVt;
+begin
+ if not Assigned(Trampo) then
+ Exit(False);
+
+ TInterceptMonitor.Enter;
+ try
+ PInfo := PTrampoDataVt(PByte(Trampo) - SizeOf(TTrampoDataVt));
+ OrgAccess := SetMemPermission(PInfo^.vAddr, 32, PAGE_EXECUTE_READWRITE);
+ try
+ PPointer(PInfo^.vAddr)^ := PInfo^.Addr;
+ finally
+ SetMemPermission(PInfo^.vAddr, 32, OrgAccess);
+ end;
+ Result := InternalFuncs.VirtualFree(Trampo, 0, MEM_RELEASE);
+ finally
+ TInterceptMonitor.Leave;
+ end;
+end;
+
+{ TInterceptMonitor }
+
+class procedure TInterceptMonitor.InternalCreate;
+begin
+ FLock := TObject.Create;
+end;
+
+class procedure TInterceptMonitor.InternalDestroy;
+begin
+ FreeAndNil(FLock);
+end;
+
+class procedure TInterceptMonitor.Enter;
+begin
+ {
+ If the current thread is working with DDL (Insert/Remove hook)..
+ others threads must wait before accessing
+ detours (Insert/Remove/...).
+ }
+{$IFNDEF FPC}
+ TMonitor.Enter(FLock);
+{$ELSE FPC}
+ EnterCriticalSection(Critical);
+{$ENDIF !FPC}
+end;
+
+class procedure TInterceptMonitor.Leave;
+begin
+ {
+ After the current thread finish it's
+ job with TIntercept .. others thread
+ can now access TIntercept .
+ }
+{$IFNDEF FPC}
+ TMonitor.Exit(FLock);
+{$ELSE}
+ LeaveCriticalSection(Critical);
+{$ENDIF}
+end;
+
+{$IFDEF MustUseGenerics }
+{ ***** BEGIN LICENSE BLOCK *****
+ *
+ * The initial developer of the original TDetour
+ * class is David Millington .
+ *
+ * ***** END LICENSE BLOCK ***** }
+
+{ TDetours }
+
+function TDetours.CheckTType: Boolean;
+var
+ LPInfo: PTypeInfo;
+begin
+ LPInfo := TypeInfo(T);
+ Result := SizeOf(T) = SizeOf(Pointer);
+ if Result then
+ Result := LPInfo.Kind = tkProcedure;
+ if not Result then
+ raise DetourException.CreateFmt(SInvalidTType, [LPInfo.Name]);
+end;
+
+constructor TDetours.Create(const TargetProc, InterceptProc: T);
+begin
+ inherited Create();
+ CheckTType;
+ SetHook(TargetProc, InterceptProc);
+end;
+
+destructor TDetours.Destroy;
+begin
+ Disable;
+ inherited;
+end;
+
+procedure TDetours.SetHook(const TargetProc, InterceptProc: T);
+begin
+ FTargetProc := TToPointer(TargetProc);
+ FInterceptProc := TToPointer(InterceptProc);
+ FNextHook := T(nil);
+ Assert(Assigned(FTargetProc) and Assigned(FInterceptProc), 'Target or replacement methods are not assigned');
+end;
+
+procedure TDetours.Disable;
+var
+ PTrampoline: Pointer;
+begin
+ if Installed then
+ begin
+ PTrampoline := TToPointer(FNextHook);
+ DDetours.InterceptRemove(PTrampoline);
+ FNextHook := T(nil);
+ end;
+end;
+
+procedure TDetours.Enable;
+begin
+ if not Installed then
+ FNextHook := PointerToT(InterceptCreate(FTargetProc, FInterceptProc));
+end;
+
+function TDetours.GetHookCount: ShortInt;
+begin
+ Result := GetNHook(FTargetProc);
+end;
+
+function TDetours.GetInstalled: Boolean;
+begin
+ Result := Assigned(TToPointer(FNextHook));
+end;
+
+function TDetours.NextHook: T;
+begin
+ Assert(Installed, SDetoursNotInstalled);
+ Result := FNextHook;
+end;
+
+function TDetours.PointerToT(const _P: Pointer): T;
+begin
+ Result := __PointerToT(_P);
+end;
+
+function TDetours.TToPointer(const _T: T): Pointer;
+begin
+ Result := __TToPointer(_T);
+end;
+
+function TDetours.__PointerToT(const _P): T;
+begin
+ Result := T(_P);
+end;
+
+function TDetours.__TToPointer(const _T): Pointer;
+begin
+ Result := Pointer(_T);
+end;
+
+{ --------------------------------------------------------------------------- }
+function BeginHooks(): Boolean;
+var
+ List: TThreadsIDList;
+begin
+ List := TThreadsIDList.Create;
+ GlobalThreadList.Add(GetCurrentThread, List);
+ Result := SuspendAllThreads(List);
+end;
+
+function EndHooks(): Boolean;
+var
+ List: TThreadsIDList;
+ currThread: THandle;
+begin
+ currThread := GetCurrentThread;
+ List := GlobalThreadList[currThread];
+ Assert(Assigned(List));
+ Result := ResumeSuspendedThreads(List);
+ GlobalThreadList.Remove(currThread);
+ FreeAndNil(List);
+end;
+
+function BeginUnHooks(): Boolean;
+begin
+ if GlobalThreadList.ContainsKey(GetCurrentThread) then
+ raise InterceptException.Create(ErrBgnUnHooks);
+ Result := BeginHooks;
+end;
+
+function EndUnHooks(): Boolean;
+begin
+ Result := EndHooks;
+end;
+{$ENDIF MustUseGenerics}
+
+var
+ SysInfo: TSystemInfo;
+
+procedure InitInternalFuncs();
+
+ function CloneFunc(Func: PByte): PByte;
+ var
+ mb, ns, Sb, fn: Byte;
+ P: PByte;
+ Inst: TInstruction;
+ begin
+ Sb := 0;
+ Func := TIntercept.GetRoot(Func);
+ Result := VirtualAlloc(nil, 64, MEM_RESERVE or MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ P := Result;
+ mb := JmpTypeToSize[tJmpRipZ];
+{$IFNDEF FPC}
+ Inst := default (TInstruction);
+{$ENDIF !FPC}
+ Inst.Archi := CPUX;
+ Inst.NextInst := Func;
+ while Sb <= mb do
+ begin
+ Inst.Addr := Inst.NextInst;
+ ns := fDecodeInst(@Inst);
+ Inc(Sb, ns);
+ end;
+ fn := MapInsts(Func, P, Sb);
+ Inc(P, fn);
+{$IFDEF CPUX64}
+ InsertJmp(P, Func + Sb, tJmpRipZ);
+{$ELSE !CPUX64}
+ InsertJmp(P, Func + Sb, tJmpRel32);
+{$ENDIF CPUX64}
+ end;
+
+begin
+{$IFDEF HookInternalFuncs}
+ @InternalFuncs.VirtualAlloc := CloneFunc(@VirtualAlloc);
+ @InternalFuncs.VirtualFree := CloneFunc(@VirtualFree);
+ @InternalFuncs.VirtualProtect := CloneFunc(@VirtualProtect);
+ @InternalFuncs.VirtualQuery := CloneFunc(@VirtualQuery);
+ @InternalFuncs.FlushInstructionCache := CloneFunc(@FlushInstructionCache);
+ @InternalFuncs.GetCurrentProcess := CloneFunc(@GetCurrentProcess);
+{$ELSE !HookInternalFuncs}
+ @InternalFuncs.VirtualAlloc := @VirtualAlloc;
+ @InternalFuncs.VirtualFree := @VirtualFree;
+ @InternalFuncs.VirtualProtect := @VirtualProtect;
+ @InternalFuncs.VirtualQuery := @VirtualQuery;
+ @InternalFuncs.FlushInstructionCache := @FlushInstructionCache;
+ @InternalFuncs.GetCurrentProcess := @GetCurrentProcess;
+{$ENDIF HookInternalFuncs}
+end;
+
+procedure FreeInternalFuncs;
+begin
+{$IFDEF HookInternalFuncs}
+ InternalFuncs.VirtualFree(@InternalFuncs.VirtualAlloc, 0, MEM_RELEASE);
+ InternalFuncs.VirtualFree(@InternalFuncs.VirtualProtect, 0, MEM_RELEASE);
+ InternalFuncs.VirtualFree(@InternalFuncs.VirtualQuery, 0, MEM_RELEASE);
+ InternalFuncs.VirtualFree(@InternalFuncs.FlushInstructionCache, 0, MEM_RELEASE);
+ InternalFuncs.VirtualFree(@InternalFuncs.GetCurrentProcess, 0, MEM_RELEASE);
+ // VirtualFree must be the last one !
+ InternalFuncs.VirtualFree(@InternalFuncs.VirtualFree, 0, MEM_RELEASE);
+{$ENDIF HookInternalFuncs}
+end;
+
+initialization
+
+TInterceptMonitor.InternalCreate;
+{$IFDEF MustUseGenerics}
+GlobalThreadList := TDictionary.Create;
+{$ENDIF MustUseGenerics}
+GetSystemInfo(SysInfo);
+SizeOfAlloc := SysInfo.dwPageSize;
+if SizeOfAlloc < (TmpSize + TrampoSize + 64) then
+ SizeOfAlloc := (TmpSize + TrampoSize + 64);
+{$IFDEF FPC}
+OpenThread := nil;
+InitializeCriticalSection(Critical);
+{$ELSE !FPC}
+@OpenThread := nil;
+{$ENDIF !FPC}
+FreeKernel := False;
+
+hKernel := GetModuleHandle(kernel32);
+if hKernel <= 0 then
+begin
+ hKernel := LoadLibrary(kernel32);
+ FreeKernel := (hKernel > 0);
+end;
+
+if hKernel > 0 then
+begin
+{$IFDEF FPC}
+ @OpenThread := GetProcAddress(hKernel, 'OpenThread');
+ @CreateToolhelp32Snapshot := GetProcAddress(hKernel, 'CreateToolhelp32Snapshot');
+ @Thread32First := GetProcAddress(hKernel, 'Thread32First');
+ @Thread32Next := GetProcAddress(hKernel, 'Thread32Next');
+{$ELSE !FPC}
+ @OpenThread := GetProcAddress(hKernel, 'OpenThread');
+{$ENDIF !FPC}
+end;
+{ The OpenThread function does not exist on OS version < Win XP }
+OpenThreadExist := (@OpenThread <> nil);
+InitInternalFuncs;
+
+finalization
+
+{$IFDEF MustUseGenerics}
+ GlobalThreadList.Free;
+{$ENDIF MustUseGenerics}
+if (FreeKernel) and (hKernel > 0) then
+ FreeLibrary(hKernel);
+FreeInternalFuncs;
+{$IFDEF FPC}
+DeleteCriticalSection(Critical);
+{$ENDIF FPC}
+TInterceptMonitor.InternalDestroy;
+
+end.
diff --git a/components/detours/Source/Defs.inc b/components/detours/Source/Defs.inc
new file mode 100644
index 00000000..6ed587d5
--- /dev/null
+++ b/components/detours/Source/Defs.inc
@@ -0,0 +1,48 @@
+{$DEFINE UseInline}
+{$DEFINE BuildThreadSafe}
+{$DEFINE UseGenerics}
+{$DEFINE UseMultiBytesNop}
+//Define HookInternalFuncs if you want to hook internal functions used by DDL core!
+{.$DEFINE HookInternalFuncs}
+//----------------------------------------------
+{$IFDEF FPC}
+ {$IFDEF CPU64}
+ {$IFNDEF CPUX64}
+ {$DEFINE CPUX64}
+ {$ENDIF !CPUX64}
+ {$ENDIF CPU64}
+ {$ASMMODE INTEL}
+{$ENDIF FPC}
+
+{$IFNDEF CPUX64}
+ {$IFNDEF CPUX86}
+ {$DEFINE CPUX86}
+ {$ENDIF !CPUX86}
+{$ENDIF !CPUX64}
+
+{$IFDEF DEBUG}
+{$R+} // Range check On
+{$ENDIF}
+
+{$IFNDEF FPC}
+ {$IF CompilerVersion >17}
+ {$DEFINE CanInline}
+ {$IFEND}
+ {$IF CompilerVersion >=21}
+ {$DEFINE GenericsExist }
+ {$IFEND}
+ {$IF CompilerVersion >=23}
+ {$DEFINE DXE2UP }
+ {$IFEND}
+ {$IF CompilerVersion >=24}
+ {$DEFINE DXE3UP }
+ {$IFEND}
+{$ENDIF !FPC}
+
+{$IF DEFINED(UseInline) and DEFINED(CanInline)}
+ {$DEFINE MustInline}
+{$IFEND}
+
+{$IF DEFINED(GenericsExist) and DEFINED(UseGenerics)}
+ {$DEFINE MustUseGenerics}
+{$IFEND}
diff --git a/components/detours/Source/InstDecode.pas b/components/detours/Source/InstDecode.pas
new file mode 100644
index 00000000..58efb5ab
--- /dev/null
+++ b/components/detours/Source/InstDecode.pas
@@ -0,0 +1,2383 @@
+// **************************************************************************************************
+// Delphi Instruction Decode Library
+// Unit InstDecode
+// https://github.com/MahdiSafsafi/delphi-detours-library
+
+// The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License");
+// you may not use this file except in compliance with the License. You may obtain a copy of the
+// License at http://www.mozilla.org/MPL/
+//
+// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
+// ANY KIND, either express or implied. See the License for the specific language governing rights
+// and limitations under the License.
+//
+// The Original Code is InstDecode.pas.
+//
+// The Initial Developer of the Original Code is Mahdi Safsafi [SMP3].
+// Portions created by Mahdi Safsafi . are Copyright (C) 2013-2017 Mahdi Safsafi .
+// All Rights Reserved.
+//
+// **************************************************************************************************
+
+{ ===============================> CHANGE LOG <======================================================
+ ==> Dec 27,2014 , Mahdi Safsafi :
+ +BugFix : IN/INS/OUT/OUTS instructions decoding.
+ +BugFix : MOV with offset instructions decoding.
+
+ ==> Version 2:
+ +Updated opcodes map .
+ +Added support to three byte escape Table
+ +Added support to vex decoding (vex three & two byte).
+ +Added support to groups opcodes instructions.
+ +Added support to decode invalid opcode .
+ +Added support to 16-bits ModRm .
+ +Added support to handling errors.
+ +Added support for mandatory prefixes.
+ +Improve Decoding Process .=> Very faster than the old one !
+ +Reduce memory usage .
+ +Removing inused fields.
+ +Better support for REX prefix.
+ +Reduce OpCodesTable data size (the old : 8670 bytes => the new one : 1020 bytes !)
+ +BugFix : FPU instructions length.
+ +BugFix : Instructions that use two immediat .
+ +BugFix : Invalid instructions .
+ +BugFix : Invalid instructions for some mandatory prefixes.
+ +Many Bug Fix.
+
+ ====================================================================================================== }
+
+unit InstDecode;
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+interface
+
+{$I Defs.inc}
+
+uses SysUtils;
+
+type
+ PInt8 = ^Int8;
+ PInt16 = ^Int16;
+ PInt32 = ^Int32;
+ PInt64 = ^Int64;
+
+ PUInt8 = ^UInt8;
+ PUInt16 = ^UInt16;
+ PUInt32 = ^UInt32;
+ PUInt64 = ^UInt64;
+
+const
+ { CPUX }
+ CPUX32 = $00; { x86-32 }
+ CPUX64 = $01; { x86-64 }
+ CPUX = {$IFDEF CPUX64}CPUX64 {$ELSE}CPUX32 {$ENDIF};
+
+ { Address Mode }
+ am16 = $01; { 16-bit addressing mode }
+ am32 = $02; { 32-bit addressing mode }
+ am64 = $03; { 64-bit addressing mode }
+ { Default Addressing Mode Depending on CPUX (32/64)bit }
+ DefAddressMode: array [0 .. 1] of Byte = (am32, am64);
+ { Used to select Addressing Mode when Address Mode Prefix is used ! }
+ AddressMode: array [0 .. 1] of Byte = (am16, am32);
+
+ { Tables }
+ tbOneByte = $01; { One Byte OpCodes Table }
+ tbTwoByte = $02; { Two Byte OpCodes Table }
+ tbThreeByte = $03; { Three Byte OpCodes Table }
+ tbFPU = $04; { FPU OpCodes Table }
+
+ { Prefixs }
+ Prf_Seg_CS = $01;
+ Prf_Seg_DS = $02;
+ Prf_Seg_ES = $04;
+ Prf_Seg_GS = $08;
+ Prf_Seg_FS = $10;
+ Prf_Seg_SS = $20;
+ Prf_OpSize = $40;
+ Prf_AddrSize = $80;
+ Prf_Lock = $100;
+ Prf_Repe = $200;
+ Prf_Repne = $400;
+ Prf_Rex = $800;
+ Prf_VEX = $1000;
+ Prf_Vex2 = Prf_VEX or $2000;
+ Prf_Vex3 = Prf_VEX or $4000;
+
+ { Segment Registers }
+ Seg_CS = $01;
+ Seg_DS = $02;
+ Seg_ES = $03;
+ Seg_GS = $04;
+ Seg_FS = $05;
+ Seg_SS = $06;
+
+ { OpSize }
+ ops8bits = $01;
+ ops16bits = $02;
+ ops32bits = $04;
+ ops48bits = $06;
+ ops64bits = $08;
+ ops128bits = $10;
+ ops256bits = $20;
+ ops512bits = $40;
+
+ { OpType }
+ otNone = $00;
+ otRET = $01; { RET Instruction }
+ otCALL = $02; { CALL Instruction }
+ otJMP = $04; { JMP Instruction }
+ otJ = $08;
+ otJcc = $10; { Conditional JUMP Instruction }
+
+ { OpKind }
+ kGrp = $01;
+ // kFPU = $02; Use OpTable !
+
+ { Options }
+ DecodeVex = $01;
+
+ { ModRm Flags }
+ mfUsed = $80; { ModRm Used }
+
+ { Sib Flags }
+ sfUsed = $01; { Sib Used }
+
+ { Displacement Flags }
+ dfUsed = $01; { Disp Used }
+ dfRip = $02; { RIP Disp }
+ dfSigned = $04; { Displacement can be signed ! }
+ dfDispOnly = $08; { Displacement Only without registers ! }
+ dfOffset = $10; { Offset coded after the opcode. }
+
+ { Immediat Flags }
+ imfUsed = $01; { Imm Used }
+
+ { Branch Flags }
+ bfUsed = $01; { JUMP/CALL Used }
+ bfRel = $02; { Relative Branch }
+ bfAbs = $04; { Absolute Branch }
+ bfIndirect = $08; { Indirect Branch }
+ bfReg = $10;
+ bfFar = bfAbs or $20; { Far Branch }
+ bfRip = $40;
+
+ { Operand Flags }
+ opdD64 = $01;
+ opdF64 = $02;
+ opdDf64 = $03;
+ opdDv64 = $04;
+
+ { Options }
+ UseVA = $01;
+
+ { General Purpose Registers }
+ rEAX = $00;
+ rECX = $01;
+ rEDX = $02;
+ rEBX = $03;
+ rESP = $04;
+ rEBP = $05;
+ rESI = $06;
+ rEDI = $07;
+
+ { Error }
+ NO_ERROR = $00;
+ INVALID_CPUX = $01;
+ INVALID_ADDRESS = $02;
+ INVALID_INSTRUCTION_LENGTH = $04;
+ ERROR_DISP_SIZE = $08;
+ ERROR_IMM_SIZE = $10;
+ ERROR_VEX_ESCAPE = $20;
+ INVALID_GROUP_OPCODE = $40;
+
+ UnknownErrorStr = 'Unknown Error';
+ InstErrorsStr: array [0 .. 7] of String = (
+ { NO_ERROR }
+ 'No error',
+ { INVALID_CPUX }
+ 'Invalid cpux',
+ { INVALID_ADDRESS }
+ 'Invalid address',
+ { INVALID_INSTRUCTION_LENGTH }
+ 'Invalid instruction length',
+ { ERROR_DISP_SIZE }
+ 'Invalid displacement size',
+ { ERROR_IMM_SIZE }
+ 'Invalid immediat size',
+ { ERROR_VEX_ESCAPE }
+ 'Invalid vex mmmmm field',
+ { INVALID_GROUP_OPCODE }
+ 'Invalid group opcode');
+
+ _vex3_ = $03;
+ _opcode_ = $01;
+ _modrm_ = $01;
+ _sib_ = $01;
+ _disp32_ = $04;
+ _imm32_ = $04;
+ _imm64_ = $08;
+ { Intel define instruction length as a 15 bytes !
+ However , it's possible to incode instructions
+ that exceed the defined length !
+ }
+ MAX_INST_LENGTH_X32 = _vex3_ + _opcode_ + _modrm_ + _sib_ + _disp32_ + _imm32_;
+ MAX_INST_LENGTH_X64 = _vex3_ + _opcode_ + _modrm_ + _sib_ + _disp32_ + _imm64_;
+ CPUX_TO_INST_LENGTH: array [0 .. 1] of ShortInt = (MAX_INST_LENGTH_X32, MAX_INST_LENGTH_X64);
+{$IFDEF CPUX64}
+ MAX_INST_LENGTH_N = MAX_INST_LENGTH_X64;
+{$ELSE !CPUX64}
+ MAX_INST_LENGTH_N = MAX_INST_LENGTH_X32;
+{$ENDIF CPUX64}
+
+var
+ { Raise Exception When Error Occurs ! }
+ RaiseExceptionOnError: Boolean = True;
+
+type
+ InstException = class(Exception);
+
+ TModRM = record
+ iMod: Byte; { ModRm.Mod Field }
+ Reg: Byte; { ModRm.Reg Field }
+ Rm: Byte; { ModRm.Rm Field }
+ Value: Byte; { ModRm Value }
+ { ModRm.Flags => See ModRmFlagsTable.inc }
+ Flags: Byte;
+ end;
+
+ PModRM = ^TModRM;
+ LPModRM = PModRM;
+
+ TSib = record
+ Scale: Byte; { SIB.Scale Field }
+ Index: Byte; { Register Index }
+ Base: Byte; { Register Base }
+ Value: Byte; { SIB Value }
+ Flags: Byte; { SIB Flags }
+ end;
+
+ PSib = ^TSib;
+ LPSib = PSib;
+
+ TImmediat = record
+ Size: Byte; { Size of Immediat => opsxxxbits }
+ Value: Int64; { Immediat Value }
+ Flags: Byte; { Sets of imfxxx }
+ end;
+
+ PImmediat = ^TImmediat;
+
+ TDisplacement = record
+ Size: Byte; { Size of Displacement => opsxxxbits }
+ Value: Int64; { Displacement Value }
+ Flags: Byte; { Sets of dfxxx }
+ end;
+
+ PDisplacement = ^TDisplacement;
+
+ TBranch = record
+ Size: Byte;
+ Value: Int64;
+ Target: PByte; { Destination Address }
+ Falgs: Byte; { Sets of bfxxx }
+ end;
+
+ PBranch = ^TBranch;
+
+ TRex = record
+ R: Boolean; { REX.R Field }
+ X: Boolean; { REX.X Field }
+ B: Boolean; { REX.B Field }
+ W: Boolean; { REX.W Field }
+ Value: Byte; { REX Value = [$40..$4F] }
+ end;
+
+ PRex = ^TRex;
+
+ TVex = record
+ {
+ ==================> N.B <==================
+ 1 => ALL FIELD ARE IN NO INVERTED FORM !
+ 2 => VEX.[R,X,B & W] ARE ACCESSIBLE THROUGH REX FIELD !
+
+ }
+ vvvv: Byte; { VEX.vvvv ==> Vector Register }
+ L: Boolean; { VEX.L ==> You should use VL instead ! }
+ PP: Byte; { VEX.PP ==> Implied Mandatory Prefixes }
+ mmmmm: Byte; { VEX.mmmmm ==> Implied Escape }
+ VL: Byte; { Vector Length }
+ end;
+
+ PVex = ^TVex;
+
+ TInternalData = record
+ MndPrf: Byte; { Mandatory Prefix }
+ zOpSize: Byte; { word or dword depending on opsize prefix ! }
+ vOpSize: Byte; { word or dword or qword depending on opsize & REX prefix ! }
+ end;
+
+ PInternalData = ^TInternalData;
+
+ TInstruction = record
+ Archi: Byte; { CPUX32 or CPUX64 ! }
+ AddrMode: Byte; { Address Mode }
+ Addr: PByte;
+ VirtualAddr: PByte;
+ NextInst: PByte; { Pointer to the Next Instruction }
+ OpCode: Byte; { OpCode Value }
+ OpType: Byte;
+ OpKind: Byte;
+ OpTable: Byte; { tbOneByte,tbTwoByte,... }
+ OperandFlags: Byte;
+ Prefixes: Word; { Sets of Prf_xxx }
+ ModRm: TModRM;
+ Sib: TSib;
+ Disp: TDisplacement;
+ Imm: TImmediat; { Primary Immediat }
+ ImmEx: TImmediat; { Secondary Immediat if used ! }
+ Branch: TBranch; { JMP & CALL }
+ SegReg: Byte; { Segment Register }
+ Rex: TRex;
+ Vex: TVex;
+ LID: TInternalData; { Internal Data }
+ Errors: Byte;
+ InstSize: Byte;
+ Options: Byte;
+ UserTag: UInt64;
+ end;
+
+ PInstruction = ^TInstruction;
+
+ TDecoderProc = procedure(PInst: PInstruction);
+
+function DecodeInst(PInst: PInstruction): ShortInt;
+
+{ Useful ModRm Routines }
+function GetModRm_Mod(const Value: Byte): Byte; {$IFDEF MustInline}inline; {$ENDIF}
+function GetModRm_Reg(const Value: Byte): Byte; {$IFDEF MustInline}inline; {$ENDIF}
+function GetModRm_Rm(const Value: Byte): Byte; {$IFDEF MustInline}inline; {$ENDIF}
+{ Useful Sib Routines }
+function GetSib_Base(const Value: Byte): Byte; {$IFDEF MustInline}inline; {$ENDIF}
+function GetSib_Index(const Value: Byte): Byte; {$IFDEF MustInline}inline; {$ENDIF}
+function GetSib_Scale(const Value: Byte): Byte; {$IFDEF MustInline}inline; {$ENDIF}
+function IsSibBaseRegValid(PInst: PInstruction): Boolean; {$IFDEF MustInline}inline; {$ENDIF}
+
+implementation
+
+{$I OpCodesTables.inc}
+{$I ModRmFlagsTables.inc}
+{ ================================== 00 ================================== }
+procedure Decode_InvalidOpCode(PInst: PInstruction); forward;
+{ ================================== 01 ================================== }
+procedure Decode_NA_ModRm(PInst: PInstruction); forward;
+{ ================================== 02 ================================== }
+procedure Decode_NA_Ib(PInst: PInstruction); forward;
+{ ================================== 03 ================================== }
+procedure Decode_NA_Iz(PInst: PInstruction); forward;
+{ ================================== 04 ================================== }
+procedure Decode_NA_I64(PInst: PInstruction); forward;
+{ ================================== 05 ================================== }
+procedure Decode_Escape_2_Byte(PInst: PInstruction); forward;
+{ ================================== 06 ================================== }
+procedure Decode_ES_Prefix(PInst: PInstruction); forward;
+{ ================================== 07 ================================== }
+procedure Decode_CS_Prefix(PInst: PInstruction); forward;
+{ ================================== 08 ================================== }
+procedure Decode_SS_Prefix(PInst: PInstruction); forward;
+{ ================================== 09 ================================== }
+procedure Decode_DS_Prefix(PInst: PInstruction); forward;
+{ ================================== 10 ================================== }
+procedure Decode_REX_Prefix(PInst: PInstruction); forward;
+{ ================================== 11 ================================== }
+procedure Decode_NA_D64(PInst: PInstruction); forward;
+{ ================================== 12 ================================== }
+procedure Decode_NA_ModRm_I64(PInst: PInstruction); forward;
+{ ================================== 13 ================================== }
+procedure Decode_FS_Prefix(PInst: PInstruction); forward;
+{ ================================== 14 ================================== }
+procedure Decode_GS_Prefix(PInst: PInstruction); forward;
+{ ================================== 15 ================================== }
+procedure Decode_OPSIZE_Prefix(PInst: PInstruction); forward;
+{ ================================== 16 ================================== }
+procedure Decode_ADSIZE_Prefix(PInst: PInstruction); forward;
+{ ================================== 17 ================================== }
+procedure Decode_NA_Iz_D64(PInst: PInstruction); forward;
+{ ================================== 18 ================================== }
+procedure Decode_NA_ModRm_Iz(PInst: PInstruction); forward;
+{ ================================== 19 ================================== }
+procedure Decode_NA_Ib_D64(PInst: PInstruction); forward;
+{ ================================== 20 ================================== }
+procedure Decode_NA_ModRm_Ib(PInst: PInstruction); forward;
+{ ================================== 21 ================================== }
+procedure Decode_NA(PInst: PInstruction); forward;
+{ ================================== 22 ================================== }
+procedure Decode_NA_Jb_Df64(PInst: PInstruction); forward;
+{ ================================== 23 ================================== }
+procedure Decode_Group_1(PInst: PInstruction); forward;
+{ ================================== 24 ================================== }
+procedure Decode_Group_1A(PInst: PInstruction); forward;
+{ ================================== 25 ================================== }
+procedure Decode_NA_CALL_Ap_I64(PInst: PInstruction); forward;
+{ ================================== 26 ================================== }
+procedure Decode_NA_OfstV(PInst: PInstruction); forward;
+{ ================================== 27 ================================== }
+procedure Decode_NA_Iv(PInst: PInstruction); forward;
+{ ================================== 28 ================================== }
+procedure Decode_Group_2(PInst: PInstruction); forward;
+{ ================================== 29 ================================== }
+procedure Decode_NA_RET_Iw_Df64(PInst: PInstruction); forward;
+{ ================================== 30 ================================== }
+procedure Decode_NA_RET_Df64(PInst: PInstruction); forward;
+{ ================================== 31 ================================== }
+procedure Decode_VEX3_Prefix(PInst: PInstruction); forward;
+{ ================================== 32 ================================== }
+procedure Decode_VEX2_Prefix(PInst: PInstruction); forward;
+{ ================================== 33 ================================== }
+procedure Decode_Group_11(PInst: PInstruction); forward;
+{ ================================== 34 ================================== }
+procedure Decode_NA_Iw_Ib_D64(PInst: PInstruction); forward;
+{ ================================== 35 ================================== }
+procedure Decode_NA_RET_Iw(PInst: PInstruction); forward;
+{ ================================== 36 ================================== }
+procedure Decode_NA_RET(PInst: PInstruction); forward;
+{ ================================== 37 ================================== }
+procedure Decode_NA_Ib_I64(PInst: PInstruction); forward;
+{ ================================== 38 ================================== }
+procedure Decode_Escape_FPU_D8(PInst: PInstruction); forward;
+{ ================================== 39 ================================== }
+procedure Decode_Escape_FPU_D9(PInst: PInstruction); forward;
+{ ================================== 40 ================================== }
+procedure Decode_Escape_FPU_DA(PInst: PInstruction); forward;
+{ ================================== 41 ================================== }
+procedure Decode_Escape_FPU_DB(PInst: PInstruction); forward;
+{ ================================== 42 ================================== }
+procedure Decode_Escape_FPU_DC(PInst: PInstruction); forward;
+{ ================================== 43 ================================== }
+procedure Decode_Escape_FPU_DD(PInst: PInstruction); forward;
+{ ================================== 44 ================================== }
+procedure Decode_Escape_FPU_DE(PInst: PInstruction); forward;
+{ ================================== 45 ================================== }
+procedure Decode_Escape_FPU_DF(PInst: PInstruction); forward;
+{ ================================== 46 ================================== }
+procedure Decode_NA_CALL_Jz_Df64(PInst: PInstruction); forward;
+{ ================================== 47 ================================== }
+procedure Decode_NA_JMP_Jz_Df64(PInst: PInstruction); forward;
+{ ================================== 48 ================================== }
+procedure Decode_NA_JMP_Ap_I64(PInst: PInstruction); forward;
+{ ================================== 49 ================================== }
+procedure Decode_NA_JMP_Jb_Df64(PInst: PInstruction); forward;
+{ ================================== 50 ================================== }
+procedure Decode_LOCK_Prefix(PInst: PInstruction); forward;
+{ ================================== 51 ================================== }
+procedure Decode_REPNE_Prefix(PInst: PInstruction); forward;
+{ ================================== 52 ================================== }
+procedure Decode_REPE_Prefix(PInst: PInstruction); forward;
+{ ================================== 53 ================================== }
+procedure Decode_Group_3(PInst: PInstruction); forward;
+{ ================================== 54 ================================== }
+procedure Decode_Group_4_INC_DEC(PInst: PInstruction); forward;
+{ ================================== 55 ================================== }
+procedure Decode_Group_5_INC_DEC(PInst: PInstruction); forward;
+{ ================================== 56 ================================== }
+procedure Decode_Group_6(PInst: PInstruction); forward;
+{ ================================== 57 ================================== }
+procedure Decode_Group_7(PInst: PInstruction); forward;
+{ ================================== 58 ================================== }
+procedure Decode_NA_CALL(PInst: PInstruction); forward;
+{ ================================== 59 ================================== }
+procedure Decode_NA_66_F2_F3_ModRm(PInst: PInstruction); forward;
+{ ================================== 60 ================================== }
+procedure Decode_NA_66_ModRm(PInst: PInstruction); forward;
+{ ================================== 61 ================================== }
+procedure Decode_NA_66_F3_ModRm(PInst: PInstruction); forward;
+{ ================================== 62 ================================== }
+procedure Decode_Group_16(PInst: PInstruction); forward;
+{ ================================== 63 ================================== }
+procedure Decode_NA_ModRm_F64(PInst: PInstruction); forward;
+{ ================================== 64 ================================== }
+procedure Decode_Escape_3_Byte(PInst: PInstruction); forward;
+{ ================================== 65 ================================== }
+procedure Decode_NA_F3_ModRm(PInst: PInstruction); forward;
+{ ================================== 66 ================================== }
+procedure Decode_66_ModRm(PInst: PInstruction); forward;
+{ ================================== 67 ================================== }
+procedure Decode_NA_66_F2_F3_ModRm_Ib(PInst: PInstruction); forward;
+{ ================================== 68 ================================== }
+procedure Decode_Group_12(PInst: PInstruction); forward;
+{ ================================== 69 ================================== }
+procedure Decode_Group_13(PInst: PInstruction); forward;
+{ ================================== 70 ================================== }
+procedure Decode_Group_14(PInst: PInstruction); forward;
+{ ================================== 71 ================================== }
+procedure Decode_66_F2_ModRm(PInst: PInstruction); forward;
+{ ================================== 72 ================================== }
+procedure Decode_NA_Jz_Df64(PInst: PInstruction); forward;
+{ ================================== 73 ================================== }
+procedure Decode_Group_15(PInst: PInstruction); forward;
+{ ================================== 74 ================================== }
+procedure Decode_F3_ModRm(PInst: PInstruction); forward;
+{ ================================== 75 ================================== }
+procedure Decode_Group_10_UD2(PInst: PInstruction); forward;
+{ ================================== 76 ================================== }
+procedure Decode_Group_8(PInst: PInstruction); forward;
+{ ================================== 77 ================================== }
+procedure Decode_NA_66_ModRm_Ib(PInst: PInstruction); forward;
+{ ================================== 78 ================================== }
+procedure Decode_Group_9(PInst: PInstruction); forward;
+{ ================================== 79 ================================== }
+procedure Decode_66_F2_F3_ModRm(PInst: PInstruction); forward;
+{ ================================== 80 ================================== }
+procedure Decode_F2_ModRm(PInst: PInstruction); forward;
+{ ================================== 81 ================================== }
+procedure Decode_SP_T38_F0_F7(PInst: PInstruction); forward;
+{ ================================== 82 ================================== }
+procedure Decode_66_ModRm_Ib(PInst: PInstruction); forward;
+{ ================================== 83 ================================== }
+procedure Decode_F2_ModRm_Ib(PInst: PInstruction); forward;
+
+procedure JumpError(PInst: PInstruction); forward;
+procedure JumpToTableTwoByte(PInst: PInstruction); forward;
+procedure JumpToTableThreeByte_38(PInst: PInstruction); forward;
+procedure JumpToTableThreeByte_3A(PInst: PInstruction); forward;
+
+procedure Decode_CALL_ModRm(PInst: PInstruction); forward;
+procedure Decode_JMP_ModRm(PInst: PInstruction); forward;
+procedure Decode_CALL_Mp(PInst: PInstruction); forward;
+procedure Decode_JMP_Mp(PInst: PInstruction); forward;
+
+const
+
+ { Convert PP To Mandatory Prefixes ! }
+ PPToMndPrf: array [0 .. 3] of Byte = ($00, $66, $F3, $F2);
+
+ { Convert LL To OpSize ! }
+ LLToOpSize: array [0 .. 3] of Word = (ops128bits, ops256bits, ops512bits, 0);
+
+ { Call escaping procedure ! }
+ mmmmmToEscProc: array [0 .. 4] of TDecoderProc = ( //
+ JumpError, { }
+ JumpToTableTwoByte, { 00001: implied 0F leading opcode byte }
+ JumpToTableThreeByte_38, { 00010: implied 0F 38 leading opcode bytes }
+ JumpToTableThreeByte_3A, { 00011: implied 0F 3A leading opcode bytes }
+ JumpError { }
+ );
+
+ DecoderProcTable: array [0 .. $54 - 1] of TDecoderProc = ( //
+ { 00 } Decode_InvalidOpCode,
+ { 01 } Decode_NA_ModRm,
+ { 02 } Decode_NA_Ib,
+ { 03 } Decode_NA_Iz,
+ { 04 } Decode_NA_I64,
+ { 05 } Decode_Escape_2_Byte,
+ { 06 } Decode_ES_Prefix,
+ { 07 } Decode_CS_Prefix,
+ { 08 } Decode_SS_Prefix,
+ { 09 } Decode_DS_Prefix,
+ { 10 } Decode_REX_Prefix,
+ { 11 } Decode_NA_D64,
+ { 12 } Decode_NA_ModRm_I64,
+ { 13 } Decode_FS_Prefix,
+ { 14 } Decode_GS_Prefix,
+ { 15 } Decode_OPSIZE_Prefix,
+ { 16 } Decode_ADSIZE_Prefix,
+ { 17 } Decode_NA_Iz_D64,
+ { 18 } Decode_NA_ModRm_Iz,
+ { 19 } Decode_NA_Ib_D64,
+ { 20 } Decode_NA_ModRm_Ib,
+ { 21 } Decode_NA,
+ { 22 } Decode_NA_Jb_Df64,
+ { 23 } Decode_Group_1,
+ { 24 } Decode_Group_1A,
+ { 25 } Decode_NA_CALL_Ap_I64,
+ { 26 } Decode_NA_OfstV,
+ { 27 } Decode_NA_Iv,
+ { 28 } Decode_Group_2,
+ { 29 } Decode_NA_RET_Iw_Df64,
+ { 30 } Decode_NA_RET_Df64,
+ { 31 } Decode_VEX3_Prefix,
+ { 32 } Decode_VEX2_Prefix,
+ { 33 } Decode_Group_11,
+ { 34 } Decode_NA_Iw_Ib_D64,
+ { 35 } Decode_NA_RET_Iw,
+ { 36 } Decode_NA_RET,
+ { 37 } Decode_NA_Ib_I64,
+ { 38 } Decode_Escape_FPU_D8,
+ { 39 } Decode_Escape_FPU_D9,
+ { 40 } Decode_Escape_FPU_DA,
+ { 41 } Decode_Escape_FPU_DB,
+ { 42 } Decode_Escape_FPU_DC,
+ { 43 } Decode_Escape_FPU_DD,
+ { 44 } Decode_Escape_FPU_DE,
+ { 45 } Decode_Escape_FPU_DF,
+ { 46 } Decode_NA_CALL_Jz_Df64,
+ { 47 } Decode_NA_JMP_Jz_Df64,
+ { 48 } Decode_NA_JMP_Ap_I64,
+ { 49 } Decode_NA_JMP_Jb_Df64,
+ { 50 } Decode_LOCK_Prefix,
+ { 51 } Decode_REPNE_Prefix,
+ { 52 } Decode_REPE_Prefix,
+ { 53 } Decode_Group_3,
+ { 54 } Decode_Group_4_INC_DEC,
+ { 55 } Decode_Group_5_INC_DEC,
+ { 56 } Decode_Group_6,
+ { 57 } Decode_Group_7,
+ { 58 } Decode_NA_CALL,
+ { 59 } Decode_NA_66_F2_F3_ModRm,
+ { 60 } Decode_NA_66_ModRm,
+ { 61 } Decode_NA_66_F3_ModRm,
+ { 62 } Decode_Group_16,
+ { 63 } Decode_NA_ModRm_F64,
+ { 64 } Decode_Escape_3_Byte,
+ { 65 } Decode_NA_F3_ModRm,
+ { 66 } Decode_66_ModRm,
+ { 67 } Decode_NA_66_F2_F3_ModRm_Ib,
+ { 68 } Decode_Group_12,
+ { 69 } Decode_Group_13,
+ { 70 } Decode_Group_14,
+ { 71 } Decode_66_F2_ModRm,
+ { 72 } Decode_NA_Jz_Df64,
+ { 73 } Decode_Group_15,
+ { 74 } Decode_F3_ModRm,
+ { 75 } Decode_Group_10_UD2,
+ { 76 } Decode_Group_8,
+ { 77 } Decode_NA_66_ModRm_Ib,
+ { 78 } Decode_Group_9,
+ { 79 } Decode_66_F2_F3_ModRm,
+ { 80 } Decode_F2_ModRm,
+ { 81 } Decode_SP_T38_F0_F7,
+ { 82 } Decode_66_ModRm_Ib,
+ { 83 } Decode_F2_ModRm_Ib);
+{$REGION 'COMMON'}
+ { ========================== COMMON =============================== }
+
+procedure SetInstError(PInst: PInstruction; Error: Byte);
+var
+ ErrStr: String;
+begin
+ ErrStr := EmptyStr;
+ if Error = NO_ERROR then
+ begin
+ { Clear Errors ! }
+ PInst^.Errors := NO_ERROR;
+ Exit;
+ end;
+ PInst^.Errors := PInst^.Errors or Error;
+
+ if RaiseExceptionOnError then
+ begin
+ if (Error > 0) and (Error < Length(InstErrorsStr)) then
+ ErrStr := InstErrorsStr[Error]
+ else
+ ErrStr := UnknownErrorStr;
+ raise InstException.Create(Format('Error %d : %s.', [Error, ErrStr]));
+ end;
+end;
+
+function GetModRm_Mod(const Value: Byte): Byte;
+begin
+ Result := Value shr 6;
+end;
+
+function GetModRm_Reg(const Value: Byte): Byte;
+begin
+ Result := (Value and $38) shr $03;
+end;
+
+function GetModRm_Rm(const Value: Byte): Byte;
+begin
+ Result := Value and 7;
+end;
+
+function GetSib_Base(const Value: Byte): Byte;
+begin
+ Result := Value and 7;
+end;
+
+function GetSib_Index(const Value: Byte): Byte;
+begin
+ Result := (Value and $38) shr $03;
+end;
+
+function GetSib_Scale(const Value: Byte): Byte;
+begin
+ Result := (1 shl (Value shr 6));
+end;
+
+function IsSibBaseRegValid(PInst: PInstruction): Boolean;
+begin
+ Result := True;
+ if PInst^.Sib.Flags and sfUsed <> 0 then
+ Result := not((PInst^.ModRm.iMod = 0) and (PInst^.Sib.Base = 5));
+end;
+
+procedure SetOpCode(PInst: PInstruction); {$IFDEF MustInline}inline; {$ENDIF}
+begin
+ PInst^.OpCode := PInst^.NextInst^;
+ Inc(PInst^.NextInst);
+end;
+
+procedure SetGroup(PInst: PInstruction); {$IFDEF MustInline}inline; {$ENDIF}
+begin
+ PInst^.OpKind := kGrp;
+end;
+
+procedure ForceOpSize(PInst: PInstruction); {$IFDEF MustInline}inline; {$ENDIF}
+begin
+ if PInst^.Archi = CPUX32 then
+ Exit;
+ PInst^.LID.vOpSize := ops64bits;
+end;
+
+procedure DecodeSib(PInst: PInstruction); {$IFDEF MustInline}inline; {$ENDIF}
+var
+ PSib: LPSib;
+begin
+ PSib := @PInst^.Sib;
+ PSib.Flags := sfUsed;
+ PSib.Value := PInst^.NextInst^;
+ PSib.Base := GetSib_Base(PSib.Value);
+ PSib.Index := GetSib_Index(PSib.Value);
+ PSib.Scale := GetSib_Scale(PSib.Value);
+ Inc(PInst^.NextInst); // Skip SIB !
+end;
+
+procedure DecodeDisp(PInst: PInstruction);
+var
+ Disp: Int64;
+ Size: Byte;
+ DispOnly: Boolean;
+begin
+ Disp := $00;
+ Size := PInst^.Disp.Size;
+ PInst^.Disp.Flags := dfUsed;
+ DispOnly := (PInst^.ModRm.iMod = $00) and (PInst^.ModRm.Rm = $05);
+
+ case Size of
+ ops8bits: Disp := (PUInt8(PInst^.NextInst)^); // and $FF;
+ ops16bits: Disp := (PUInt16(PInst^.NextInst)^); // and $FFFF;
+ ops32bits:
+ begin
+ Disp := (PUInt32(PInst^.NextInst)^); // and $FFFFFFFF;
+ if (PInst^.Archi = CPUX64) and DispOnly then
+ { RIP disp ! }
+ PInst^.Disp.Flags := PInst^.Disp.Flags or dfRip;
+ end;
+ else SetInstError(PInst, ERROR_DISP_SIZE);
+ end;
+
+ if DispOnly then
+ PInst^.Disp.Flags := PInst^.Disp.Flags or dfDispOnly
+ else
+ PInst^.Disp.Flags := PInst^.Disp.Flags or dfSigned;
+
+ PInst^.Disp.Value := Disp;
+ Inc(PInst^.NextInst, Size) // Skip Disp !
+end;
+
+procedure Decode_ModRm(PInst: PInstruction);
+var
+ PModRM: LPModRM;
+ SibUsed: Boolean;
+const
+ { Get Disp Size from ModRm . }
+ ModRMFlagsToDispSize: array [0 .. 4] of Byte = (0, ops8bits, ops16bits, 0, ops32bits);
+begin
+ PModRM := @PInst^.ModRm;
+ PModRM.Value := PInst^.NextInst^;
+ PModRM.iMod := GetModRm_Mod(PModRM.Value);
+ PModRM.Reg := GetModRm_Reg(PModRM.Value);
+ PModRM.Rm := GetModRm_Rm(PModRM.Value);
+ PModRM.Flags := ModRMFlags[PInst^.AddrMode][PModRM.Value];
+
+ PInst^.Disp.Size := ModRMFlagsToDispSize[(PModRM.Flags shr 1) and 7];
+ Inc(PInst^.NextInst); // Skip ModRM !
+
+ SibUsed := (PModRM.Flags and $10 > 0); { SibUsed ! }
+
+ if SibUsed then
+ begin
+ DecodeSib(PInst);
+ { if the base is not valid ==> there is a disp32 .
+ But the disp can be 8bit ==> we need to check first
+ if the disp does not exist !
+ }
+ if (PInst^.Disp.Size = 0) and (not IsSibBaseRegValid(PInst)) then
+ PInst^.Disp.Size := ops32bits;
+ end;
+
+ if PInst^.Disp.Size > 0 then
+ DecodeDisp(PInst);
+
+ { ModRm Exists ! }
+ PModRM.Flags := PModRM.Flags or mfUsed;
+end;
+
+procedure Decode_Imm(PInst: PInstruction; immSize: Byte);
+var
+ Imm: Int64;
+ PImm: PImmediat;
+begin
+ Imm := $00;
+ case immSize of
+ ops8bits: Imm := (PInt8(PInst^.NextInst)^);
+ ops16bits: Imm := (PInt16(PInst^.NextInst)^);
+ ops32bits: Imm := (PInt32(PInst^.NextInst)^);
+ ops64bits: Imm := (PInt64(PInst^.NextInst)^);
+ else SetInstError(PInst, ERROR_IMM_SIZE);
+ end;
+
+ {
+ If Imm field already used => get the extra Imm
+ }
+ if PInst^.Imm.Flags and imfUsed <> $00 then
+ PImm := @PInst^.ImmEx
+ else
+ PImm := @PInst^.Imm;
+
+ PImm.Flags := imfUsed;
+ PImm.Value := Imm;
+ PImm.Size := immSize;
+ Inc(PInst^.NextInst, immSize); // Skip Immediat !
+end;
+
+procedure Decode_J(PInst: PInstruction; Size: Byte);
+var
+ Value: Int64;
+ VA: PByte;
+begin
+ Value := $00;
+ case Size of
+ ops8bits: Value := (PInt8(PInst^.NextInst)^);
+ ops16bits: Value := (PInt16(PInst^.NextInst)^);
+ ops32bits: Value := (PInt32(PInst^.NextInst)^);
+ ops64bits: Value := (PInt64(PInst^.NextInst)^);
+ end;
+ Inc(PInst^.NextInst, Size);
+ if PInst^.OpType = otNone then
+ PInst^.OpType := otJ;
+ if PInst^.OpCode in [$70 .. $8F] then
+ PInst^.OpType := otJ or otJcc;
+ if Assigned(PInst^.VirtualAddr) then
+ VA := PInst^.VirtualAddr + (PInst^.NextInst - PInst^.Addr)
+ else
+ VA := PInst^.NextInst;
+ PInst^.Branch.Size := Size;
+ PInst^.Branch.Falgs := bfUsed or bfRel;
+ PInst^.Branch.Value := Value;
+ PInst^.Branch.Target := VA + Value;
+end;
+
+procedure Decode_Branch_ModRm(PInst: PInstruction);
+var
+ P: PByte;
+ VA: PByte;
+begin
+ SetOpCode(PInst);
+ Decode_ModRm(PInst);
+ PInst^.Branch.Value := PInst^.Disp.Value;
+ PInst^.Branch.Size := PInst^.Disp.Size;
+ PInst^.Branch.Falgs := bfUsed or bfIndirect or bfAbs;
+ if Assigned(PInst^.VirtualAddr) then
+ VA := PInst^.VirtualAddr + (PInst^.NextInst - PInst^.Addr)
+ else
+ VA := PInst^.NextInst;
+ if (PInst^.ModRm.iMod = $00) and (PInst^.ModRm.Rm = $05) then
+ begin
+ { Memory = Displacement }
+ if PInst^.Archi = CPUX64 then
+ begin
+ if PInst^.Prefixes and Prf_AddrSize <> 0 then
+ { Displacement = EIP + Offset }
+ VA := PByte(UInt64(VA) and $FFFFFFFF);
+ { Displacement = RIP + Offset }
+ PInst^.Branch.Falgs := PInst^.Branch.Falgs or bfRip;
+ P := VA + Int32(PInst^.Disp.Value);
+ { Memory 64-bits }
+ PInst^.Branch.Target := PByte(PUInt64(P)^);
+ end
+ else
+ begin
+ { No RIP }
+ P := PByte(UInt32(PInst^.Disp.Value));
+ if PInst^.Prefixes and Prf_OpSize <> 0 then
+ { Memory 16-bits }
+ PInst^.Branch.Target := PByte(PUInt16(P)^)
+ else
+ { Memory 32-bits }
+ PInst^.Branch.Target := PByte(PUInt32(P)^);
+ end;
+ end
+ else
+ begin
+ { Memory = Displacement + Register }
+ PInst^.Branch.Falgs := PInst^.Branch.Falgs or bfReg;
+ PInst^.Branch.Target := nil;
+ end;
+end;
+
+procedure Decode_Ap(PInst: PInstruction);
+begin
+ SetOpCode(PInst);
+ PInst^.Branch.Falgs := bfUsed or bfFar;
+ { We must clear the upper word ! }
+ PInst^.Branch.Value := PUInt64(PInst^.NextInst)^ and $FFFFFFFFFFFF;
+ PInst^.Branch.Size := ops48bits;
+ PInst^.Branch.Target := nil;
+ Inc(PInst^.NextInst, ops48bits);
+end;
+
+procedure Decode_Mp(PInst: PInstruction);
+begin
+ SetOpCode(PInst);
+ PInst^.Branch.Falgs := bfUsed or bfFar;
+ Decode_ModRm(PInst);
+ PInst^.Branch.Value := PInst^.Disp.Value;
+ PInst^.Branch.Size := PInst^.Disp.Size;
+ PInst^.Branch.Target := nil;
+end;
+
+procedure Decode_InvalidOpCode(PInst: PInstruction); {$IFDEF MustInline}inline;
+{$ENDIF}
+begin
+ SetOpCode(PInst);
+end;
+
+procedure Decode_Invalid_Group(PInst: PInstruction); {$IFDEF MustInline}inline;
+{$ENDIF}
+begin
+ SetOpCode(PInst);
+ Inc(PInst^.NextInst);
+end;
+
+procedure Decode_Invalid_FPU(PInst: PInstruction); {$IFDEF MustInline}inline;
+{$ENDIF}
+begin
+ SetOpCode(PInst);
+ Inc(PInst^.NextInst);
+end;
+
+{$ENDREGION}
+{$REGION 'PREFIXES'}
+{ ========================== PREFIXES =============================== }
+
+procedure Decode_ES_Prefix(PInst: PInstruction);
+begin
+ { ES Segment Override Prefix }
+ Inc(PInst^.NextInst);
+ PInst^.Prefixes := PInst^.Prefixes or Prf_Seg_ES;
+ PInst^.SegReg := Seg_ES;
+ DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);
+end;
+
+procedure Decode_CS_Prefix(PInst: PInstruction);
+begin
+ { CS Segment Override Prefix }
+ Inc(PInst^.NextInst);
+ PInst^.Prefixes := PInst^.Prefixes or Prf_Seg_CS;
+ PInst^.SegReg := Seg_CS;
+ DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);
+end;
+
+procedure Decode_SS_Prefix(PInst: PInstruction);
+begin
+ { SS Segment Override Prefix }
+ Inc(PInst^.NextInst);
+ PInst^.Prefixes := PInst^.Prefixes or Prf_Seg_SS;
+ PInst^.SegReg := Seg_SS;
+ DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);
+end;
+
+procedure Decode_DS_Prefix(PInst: PInstruction);
+begin
+ { DS Segment Override Prefix }
+ Inc(PInst^.NextInst);
+ PInst^.Prefixes := PInst^.Prefixes or Prf_Seg_DS;
+ PInst^.SegReg := Seg_DS;
+ DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);
+end;
+
+procedure Decode_REX_Prefix(PInst: PInstruction);
+begin
+ { REX Prefix valid only on PM64! }
+ if PInst^.Archi = CPUX32 then
+ begin
+ { INC/DEC REG }
+ Decode_NA(PInst);
+ Exit;
+ end;
+ PInst^.Prefixes := PInst^.Prefixes or Prf_Rex;
+ PInst^.Rex.Value := PInst^.NextInst^;
+ PInst^.Rex.B := (PInst^.Rex.Value and 1 <> 0);
+ PInst^.Rex.X := (PInst^.Rex.Value and 2 <> 0);
+ PInst^.Rex.R := (PInst^.Rex.Value and 4 <> 0);
+ PInst^.Rex.W := (PInst^.Rex.Value and 8 <> 0);
+
+ if PInst^.Rex.W then
+ PInst^.LID.vOpSize := ops64bits;
+
+ Inc(PInst^.NextInst); // Skip Rex .
+ DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);
+end;
+
+procedure Decode_FS_Prefix(PInst: PInstruction);
+begin
+ { FS Segment Override Prefix }
+ Inc(PInst^.NextInst);
+ PInst^.Prefixes := PInst^.Prefixes or Prf_Seg_FS;
+ PInst^.SegReg := Seg_FS;
+ DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);
+end;
+
+procedure Decode_GS_Prefix(PInst: PInstruction);
+begin
+ { GS Segment Override Prefix }
+ Inc(PInst^.NextInst);
+ PInst^.Prefixes := PInst^.Prefixes or Prf_Seg_GS;
+ PInst^.SegReg := Seg_GS;
+ DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);
+end;
+
+procedure Decode_OPSIZE_Prefix(PInst: PInstruction);
+begin
+ PInst^.Prefixes := PInst^.Prefixes or Prf_OpSize;
+ PInst^.LID.vOpSize := ops16bits;
+ PInst^.LID.zOpSize := ops16bits;
+ PInst^.LID.MndPrf := $66;
+ Inc(PInst^.NextInst);
+ DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);
+end;
+
+procedure Decode_ADSIZE_Prefix(PInst: PInstruction);
+begin
+ PInst^.Prefixes := PInst^.Prefixes or Prf_AddrSize;
+ Inc(PInst^.NextInst);
+ PInst^.AddrMode := AddressMode[PInst^.Archi];
+ DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);
+end;
+
+procedure Decode_VEX3_Prefix(PInst: PInstruction);
+var
+ P: Byte;
+ Q: PByte;
+ R, X: Boolean;
+begin
+ if PInst^.Options and DecodeVex = 0 then
+ begin
+ Decode_NA_ModRm(PInst);
+ Exit;
+ end;
+ if PInst^.Archi = CPUX32 then
+ begin
+ Q := PInst^.NextInst;
+ Inc(Q);
+ R := (Q^ and $80 <> 0);
+ X := (Q^ and $40 <> 0);
+ {
+ if R & X are set ==> Vex prefix is valid !
+ otherwise the instruction is LES .
+ }
+ if not(R and X) then
+ begin
+ { LES instruction }
+ Decode_NA_ModRm(PInst);
+ Exit;
+ end;
+ end;
+
+ Inc(PInst^.NextInst); // Skip $C4 !
+ PInst^.Prefixes := PInst^.Prefixes or Prf_Vex3;
+ P := PInst^.NextInst^; // P0
+ PInst^.Rex.R := not(P and $80 <> 0);
+ PInst^.Rex.X := not(P and $40 <> 0);
+ PInst^.Rex.B := not(P and $20 <> 0);
+ PInst^.Vex.mmmmm := (P and $1F);
+ Inc(PInst^.NextInst); // Skip P0
+ P := PInst^.NextInst^; // P1
+ Inc(PInst^.NextInst); // Skip P1
+ PInst^.Rex.W := (P and $80 <> 0);
+ PInst^.Vex.vvvv := $0F - ((P and $78) shr 3);
+ PInst^.Vex.L := (P and 4 <> 0);
+ PInst^.Vex.PP := (P and 3);
+ PInst^.Vex.VL := LLToOpSize[Byte(PInst^.Vex.L)];
+ PInst^.LID.MndPrf := PPToMndPrf[PInst^.Vex.PP];
+ mmmmmToEscProc[PInst^.Vex.mmmmm](PInst);
+end;
+
+procedure Decode_VEX2_Prefix(PInst: PInstruction);
+var
+ P: Byte;
+ Q: PByte;
+ R: Boolean;
+begin
+ if PInst^.Options and DecodeVex = 0 then
+ begin
+ Decode_NA_ModRm(PInst);
+ Exit;
+ end;
+ if PInst^.Archi = CPUX32 then
+ begin
+ Q := PInst^.NextInst;
+ Inc(Q);
+ R := (Q^ and $80 <> 0);
+ {
+ if R is set ==> Vex prefix is valid !
+ otherwise the instruction is LDS.
+ }
+ if not R then
+ begin
+ { LDS instruction }
+ Decode_NA_ModRm(PInst);
+ Exit;
+ end;
+ end;
+
+ Inc(PInst^.NextInst); // Skip $C5 !
+ PInst^.Prefixes := PInst^.Prefixes or Prf_Vex2;
+ P := PInst^.NextInst^;
+ PInst^.Rex.R := not(P and $80 <> 0);
+ PInst^.Vex.vvvv := $0F - ((P and $78) shr 3);
+ PInst^.Vex.L := (P and 4 <> 0);
+ PInst^.Vex.PP := (P and 3);
+ PInst^.Vex.VL := LLToOpSize[Byte(PInst^.Vex.L)];
+ PInst^.LID.MndPrf := PPToMndPrf[PInst^.Vex.PP];
+ Inc(PInst^.NextInst); // Skip P0 !
+ DecoderProcTable[TwoByteTable[PInst^.NextInst^]](PInst);
+end;
+
+procedure Decode_LOCK_Prefix(PInst: PInstruction);
+begin
+ PInst^.Prefixes := PInst^.Prefixes or Prf_Lock;
+ Inc(PInst^.NextInst);
+ DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);
+end;
+
+procedure Decode_REPNE_Prefix(PInst: PInstruction);
+begin
+ PInst^.Prefixes := PInst^.Prefixes or Prf_Repne;
+ PInst^.LID.MndPrf := $F2;
+ Inc(PInst^.NextInst);
+ DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);
+end;
+
+procedure Decode_REPE_Prefix(PInst: PInstruction);
+begin
+ PInst^.Prefixes := PInst^.Prefixes or Prf_Repe;
+ PInst^.LID.MndPrf := $F3;
+ Inc(PInst^.NextInst);
+ DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);
+end;
+{$ENDREGION}
+{$REGION 'ESCAPE'}
+{ ========================== ESCAPE =============================== }
+
+procedure JumpError(PInst: PInstruction);
+begin
+ { Wrong Vex.mmmmm value ! }
+ SetInstError(PInst, ERROR_VEX_ESCAPE);
+end;
+
+procedure JumpToTableTwoByte(PInst: PInstruction);
+begin
+ { Implied $0F OpCode => Jump to table TwoByteTable }
+ PInst^.OpTable := tbTwoByte;
+ DecoderProcTable[TwoByteTable[PInst^.NextInst^]](PInst);
+end;
+
+procedure JumpToTableThreeByte_38(PInst: PInstruction);
+begin
+ { Implied $0F$38 OpCodes => Jump to table ThreeByteTable.38 }
+ PInst^.OpTable := tbThreeByte;
+ DecoderProcTable[ThreeByteTable38[PInst^.NextInst^]](PInst);
+end;
+
+procedure JumpToTableThreeByte_3A(PInst: PInstruction);
+begin
+ { Implied $0F$3A OpCodes => Jump to table ThreeByteTable.3A }
+ PInst^.OpTable := tbThreeByte;
+ DecoderProcTable[ThreeByteTable3A[PInst^.NextInst^]](PInst);
+end;
+
+procedure Decode_Escape_2_Byte(PInst: PInstruction);
+begin
+ { Two Byte OpCode Escape ! }
+ PInst^.OpTable := tbTwoByte;
+ Inc(PInst^.NextInst);
+ DecoderProcTable[TwoByteTable[PInst^.NextInst^]](PInst);
+end;
+
+procedure Decode_Escape_3_Byte(PInst: PInstruction);
+var
+ P: Byte;
+begin
+ { Three Byte OpCode Escape ! }
+ PInst^.OpTable := tbThreeByte;
+ P := PInst^.NextInst^;
+ Inc(PInst^.NextInst);
+ if P = $38 then
+ DecoderProcTable[ThreeByteTable38[PInst^.NextInst^]](PInst)
+ else
+ DecoderProcTable[ThreeByteTable3A[PInst^.NextInst^]](PInst);
+end;
+
+{$ENDREGION}
+{$REGION 'FPU'}
+{ ========================== FPU =============================== }
+
+procedure Decode_Escape_FPU_D8(PInst: PInstruction);
+begin
+ { All OpCode are valid for $D8 ! }
+ PInst^.OpTable := tbFPU;
+ Decode_NA_ModRm(PInst);
+end;
+
+procedure Decode_Escape_FPU_D9(PInst: PInstruction);
+var
+ P: PByte;
+ ModRm: Byte;
+ Reg: Byte;
+begin
+ PInst^.OpTable := tbFPU;
+ P := PInst^.NextInst;
+ Inc(P);
+ ModRm := P^;
+ Reg := GetModRm_Reg(ModRm);
+ if ModRm < $C0 then
+ begin
+ if Reg = $01 then
+ begin
+ Decode_Invalid_FPU(PInst);
+ Exit;
+ end;
+ end
+ else
+ begin
+ if ModRm in [$D1 .. $DF, $E2, $E3, $EF] then
+ begin
+ Decode_Invalid_FPU(PInst);
+ Exit;
+ end;
+ end;
+ Decode_NA_ModRm(PInst);
+end;
+
+procedure Decode_Escape_FPU_DA(PInst: PInstruction);
+var
+ P: PByte;
+ ModRm: Byte;
+begin
+ PInst^.OpTable := tbFPU;
+ P := PInst^.NextInst;
+ Inc(P);
+ ModRm := P^;
+ if ModRm > $C0 then
+ begin
+ if ModRm in [$E0 .. $E8, $EA .. $EF, $F0 .. $FF] then
+ begin
+ Decode_Invalid_FPU(PInst);
+ Exit;
+ end;
+ end;
+ Decode_NA_ModRm(PInst);
+end;
+
+procedure Decode_Escape_FPU_DB(PInst: PInstruction);
+var
+ P: PByte;
+ ModRm: Byte;
+ Reg: Byte;
+begin
+ PInst^.OpTable := tbFPU;
+ P := PInst^.NextInst;
+ Inc(P);
+ ModRm := P^;
+ Reg := GetModRm_Reg(ModRm);
+ if ModRm < $C0 then
+ begin
+ if (Reg = $04) or (Reg = $06) then
+ begin
+ Decode_Invalid_FPU(PInst);
+ Exit;
+ end;
+ end
+ else
+ begin
+ if ModRm in [$E0, $E1, $E4 .. $E7, $F8 .. $FF] then
+ begin
+ Decode_Invalid_FPU(PInst);
+ Exit;
+ end;
+ end;
+ Decode_NA_ModRm(PInst);
+end;
+
+procedure Decode_Escape_FPU_DC(PInst: PInstruction);
+var
+ P: PByte;
+ ModRm: Byte;
+begin
+ PInst^.OpTable := tbFPU;
+ P := PInst^.NextInst;
+ Inc(P);
+ ModRm := P^;
+ if ModRm > $C0 then
+ begin
+ if ModRm in [$D0 .. $DF] then
+ begin
+ Decode_Invalid_FPU(PInst);
+ Exit;
+ end;
+ end;
+ Decode_NA_ModRm(PInst);
+end;
+
+procedure Decode_Escape_FPU_DD(PInst: PInstruction);
+var
+ P: PByte;
+ ModRm: Byte;
+ Reg: Byte;
+begin
+ PInst^.OpTable := tbFPU;
+ P := PInst^.NextInst;
+ Inc(P);
+ ModRm := P^;
+ Reg := GetModRm_Reg(ModRm);
+ if ModRm < $C0 then
+ begin
+ if (Reg = $05) then
+ begin
+ Decode_Invalid_FPU(PInst);
+ Exit;
+ end;
+ end
+ else
+ begin
+ if ModRm in [$C8 .. $CF, $F0 .. $FF] then
+ begin
+ Decode_Invalid_FPU(PInst);
+ Exit;
+ end;
+ end;
+ Decode_NA_ModRm(PInst);
+end;
+
+procedure Decode_Escape_FPU_DE(PInst: PInstruction);
+var
+ P: PByte;
+ ModRm: Byte;
+begin
+ PInst^.OpTable := tbFPU;
+ P := PInst^.NextInst;
+ Inc(P);
+ ModRm := P^;
+ if ModRm > $C0 then
+ begin
+ if ModRm in [$D0 .. $D8, $DA .. $DF] then
+ begin
+ Decode_Invalid_FPU(PInst);
+ Exit;
+ end;
+ end;
+ Decode_NA_ModRm(PInst);
+end;
+
+procedure Decode_Escape_FPU_DF(PInst: PInstruction);
+var
+ P: PByte;
+ ModRm: Byte;
+begin
+ PInst^.OpTable := tbFPU;
+ P := PInst^.NextInst;
+ Inc(P);
+ ModRm := P^;
+ if ModRm > $C0 then
+ begin
+ if ModRm in [$C0 .. $CF, $D0 .. $DF, $E1 .. $E7, $F8 .. $FF] then
+ begin
+ Decode_Invalid_FPU(PInst);
+ Exit;
+ end;
+ end;
+ Decode_NA_ModRm(PInst);
+end;
+
+{$ENDREGION}
+{$REGION 'GROUPS'}
+{ ========================== GROUPS =============================== }
+
+procedure Decode_Group_1(PInst: PInstruction);
+begin
+ SetGroup(PInst);
+ if not(PInst^.NextInst^ in [$80 .. $83]) then
+ SetInstError(PInst, INVALID_GROUP_OPCODE);
+ if PInst^.NextInst^ = $81 then
+ Decode_NA_ModRm_Iz(PInst)
+ else
+ Decode_NA_ModRm_Ib(PInst);
+end;
+
+procedure Decode_Group_1A(PInst: PInstruction);
+var
+ P: PByte;
+ Reg: Byte;
+begin
+ SetGroup(PInst);
+ if (PInst^.NextInst^ <> $8F) then
+ SetInstError(PInst, INVALID_GROUP_OPCODE);
+ P := PInst^.NextInst;
+ Inc(P); // ModRm !
+ Reg := GetModRm_Reg(P^);
+ if (Reg = $00) then
+ begin
+ Decode_NA_ModRm(PInst);
+ Exit;
+ end;
+ Decode_Invalid_Group(PInst);
+end;
+
+procedure Decode_Group_2(PInst: PInstruction);
+begin
+ SetGroup(PInst);
+ if not(PInst^.NextInst^ in [$C0 .. $C1, $D0 .. $D3]) then
+ SetInstError(PInst, INVALID_GROUP_OPCODE);
+ if (PInst^.NextInst^ in [$C0, $C1]) then
+ Decode_NA_ModRm_Ib(PInst)
+ else
+ Decode_NA_ModRm(PInst);
+end;
+
+procedure Decode_Group_3(PInst: PInstruction);
+var
+ P: PByte;
+ Reg: Byte;
+begin
+ SetGroup(PInst);
+ if not(PInst^.NextInst^ in [$F6, $F7]) then
+ SetInstError(PInst, INVALID_GROUP_OPCODE);
+ P := PInst^.NextInst;
+ Inc(P);
+ Reg := GetModRm_Reg(P^);
+ if (Reg < $02) then
+ begin
+ { [TEST Reg,Immb] & [TEST Reg,Immz] }
+ if PInst^.NextInst^ = $F6 then
+ Decode_NA_ModRm_Ib(PInst)
+ else
+ Decode_NA_ModRm_Iz(PInst);
+ Exit;
+ end;
+ Decode_NA_ModRm(PInst);
+end;
+
+procedure Decode_Group_4_INC_DEC(PInst: PInstruction);
+var
+ P: PByte;
+ Reg: Byte;
+begin
+ SetGroup(PInst);
+ Assert(PInst^.NextInst^ = $FE);
+ P := PInst^.NextInst;
+ Inc(P); // ModRm
+ Reg := GetModRm_Reg(P^);
+ if (Reg < $02) then
+ begin
+ { INC/DEC REG }
+ Decode_NA_ModRm(PInst);
+ Exit;
+ end;
+ Decode_Invalid_Group(PInst);
+end;
+
+procedure Decode_Group_5_INC_DEC(PInst: PInstruction);
+var
+ Reg: Byte;
+ P: PByte;
+const
+ GroupProc: array [0 .. 7] of TDecoderProc = ( //
+ { 00 } Decode_NA_ModRm, { INC Ev }
+ { 01 } Decode_NA_ModRm, { DEC Ev }
+ { 02 } Decode_CALL_ModRm, { CALL Ev }
+ { 03 } Decode_CALL_Mp, { CALL Mp }
+ { 04 } Decode_JMP_ModRm, { JMP Ev }
+ { 05 } Decode_JMP_Mp, { JMP Mp }
+ { 06 } Decode_NA_ModRm, { PUSH Ev }
+ { 07 } Decode_Invalid_Group { InvalidOpCode }
+ );
+begin
+ SetGroup(PInst);
+ if (PInst^.NextInst^ <> $FF) then
+ SetInstError(PInst, INVALID_GROUP_OPCODE);
+ P := PInst^.NextInst;
+ Inc(P); // ModRm
+ Reg := GetModRm_Reg(P^);
+ GroupProc[Reg](PInst);
+end;
+
+procedure Decode_Group_6(PInst: PInstruction);
+var
+ P: PByte;
+ Reg: Byte;
+begin
+ SetGroup(PInst);
+ if (PInst^.OpTable <> tbTwoByte) and (PInst^.NextInst^ <> $00) then
+ SetInstError(PInst, INVALID_GROUP_OPCODE);
+ P := PInst^.NextInst;
+ Inc(P);
+ Reg := GetModRm_Reg(P^);
+ if Reg = $07 then
+ begin
+ Decode_Invalid_Group(PInst);
+ Exit;
+ end;
+ Decode_NA_ModRm(PInst);
+end;
+
+procedure Decode_Group_7(PInst: PInstruction);
+var
+ P: PByte;
+ iMod, Reg: Byte;
+begin
+ SetGroup(PInst);
+ if (PInst^.OpTable <> tbTwoByte) and (PInst^.NextInst^ <> $01) then
+ SetInstError(PInst, INVALID_GROUP_OPCODE);
+ P := PInst^.NextInst;
+ Inc(P);
+ iMod := GetModRm_Mod(P^);
+ Reg := GetModRm_Reg(P^);
+ if (Reg = $04) or (Reg = $06) then
+ begin
+ Decode_NA_ModRm(PInst);
+ Exit;
+ end
+ else if Reg = $05 then
+ begin
+ Decode_Invalid_Group(PInst);
+ Exit;
+ end;
+ if iMod <> $03 then
+ begin
+ Decode_NA_ModRm(PInst);
+ Exit;
+ end;
+ Decode_Invalid_Group(PInst);
+end;
+
+procedure Decode_Group_8(PInst: PInstruction);
+var
+ P: PByte;
+ Reg: Byte;
+begin
+ SetGroup(PInst);
+ if (PInst^.OpTable <> tbTwoByte) and (PInst^.NextInst^ <> $BA) then
+ SetInstError(PInst, INVALID_GROUP_OPCODE);
+ P := PInst^.NextInst;
+ Inc(P);
+ Reg := GetModRm_Reg(P^);
+ if Reg > $03 then
+ begin
+ Decode_NA_ModRm_Ib(PInst);
+ Exit;
+ end;
+ Decode_Invalid_Group(PInst);
+end;
+
+procedure Decode_Group_9(PInst: PInstruction);
+var
+ P: PByte;
+ iMod, Reg: Byte;
+begin
+ SetGroup(PInst);
+ if (PInst^.OpTable <> tbTwoByte) and (PInst^.NextInst^ <> $C7) then
+ SetInstError(PInst, INVALID_GROUP_OPCODE);
+ P := PInst^.NextInst;
+ Inc(P);
+ iMod := GetModRm_Mod(P^);
+ Reg := GetModRm_Reg(P^);
+ if (iMod = $03) and (Reg > $05) then
+ begin
+ Decode_NA_ModRm(PInst);
+ Exit;
+ end;
+
+ if (iMod <> $03) then
+ begin
+ { Mod = Mem }
+ if (((PInst^.LID.MndPrf = $00) and (Reg = $01)) or //
+ ((PInst^.LID.MndPrf = $66) and (Reg = $06)) or //
+ ((PInst^.LID.MndPrf = $F3) and (Reg > $05))) then
+ begin
+ Decode_NA_ModRm(PInst);
+ Exit;
+ end;
+ end;
+ Decode_Invalid_Group(PInst);
+end;
+
+procedure Decode_Group_10_UD2(PInst: PInstruction);
+begin
+ SetGroup(PInst);
+ Decode_InvalidOpCode(PInst);
+end;
+
+procedure Decode_Group_11(PInst: PInstruction);
+var
+ P: PByte;
+ Reg: Byte;
+begin
+ SetGroup(PInst);
+ if not(PInst^.NextInst^ in [$C6, $C7]) then
+ SetInstError(PInst, INVALID_GROUP_OPCODE);
+ P := PInst^.NextInst;
+ Inc(P);
+ Reg := GetModRm_Reg(P^);
+ if PInst^.NextInst^ = $C6 then
+ begin
+ if (Reg = $00) then
+ begin
+ { XABORT Instruction }
+ Decode_NA_ModRm_Ib(PInst);
+ Exit;
+ end
+ else if (Reg = $07) then
+ begin
+ Decode_NA_Ib(PInst);
+ Exit;
+ end
+ end
+ else if PInst^.NextInst^ = $C7 then
+ begin
+ if Reg = $00 then
+ begin
+ Decode_NA_ModRm_Iz(PInst);
+ Exit;
+ end
+ else if Reg = $07 then
+ begin
+ { XBEGIN Instruction }
+ SetOpCode(PInst);
+ Inc(PInst^.NextInst);
+ Decode_J(PInst, PInst^.LID.zOpSize);
+ PInst^.OpType := $00;
+ Exit;
+ end;
+ end;
+ Decode_Invalid_Group(PInst);
+end;
+
+procedure Decode_Group_12(PInst: PInstruction);
+var
+ P: PByte;
+ iMod, Reg: Byte;
+begin
+ SetGroup(PInst);
+ { Group 12 & 13 }
+ if (PInst^.OpTable <> tbTwoByte) and not(PInst^.NextInst^ in [$71, $72]) then
+ SetInstError(PInst, INVALID_GROUP_OPCODE);
+ P := PInst^.NextInst;
+ Inc(P);
+ iMod := GetModRm_Mod(P^);
+ Reg := GetModRm_Reg(P^);
+ if (iMod = $03) and (Reg in [$02, $04, $06]) then
+ begin
+ Decode_NA_ModRm_Ib(PInst);
+ Exit;
+ end;
+ Decode_Invalid_Group(PInst);
+end;
+
+procedure Decode_Group_13(PInst: PInstruction);
+begin
+ SetGroup(PInst);
+ { Group 13 has the same instructions signature as Group 12 ! }
+ Decode_Group_12(PInst);
+end;
+
+procedure Decode_Group_14(PInst: PInstruction);
+var
+ P: PByte;
+ iMod, Reg: Byte;
+begin
+ SetGroup(PInst);
+ if (PInst^.OpTable <> tbTwoByte) and (PInst^.NextInst^ <> $73) then
+ SetInstError(PInst, INVALID_GROUP_OPCODE);
+ P := PInst^.NextInst;
+ Inc(P);
+ iMod := GetModRm_Mod(P^);
+ Reg := GetModRm_Reg(P^);
+ if iMod = $03 then
+ begin
+ if (Reg = $02) or (Reg = $06) then
+ begin
+ Decode_NA_ModRm_Ib(PInst);
+ Exit;
+ end;
+ if (PInst^.LID.MndPrf = $66) and ((Reg = $03) or (Reg = $07)) then
+ begin
+ Decode_NA_ModRm_Ib(PInst);
+ Exit;
+ end;
+ end;
+ Decode_Invalid_Group(PInst);
+end;
+
+procedure Decode_Group_15(PInst: PInstruction);
+var
+ P: PByte;
+ iMod, Reg: Byte;
+begin
+ SetGroup(PInst);
+ if (PInst^.OpTable <> tbTwoByte) and (PInst^.NextInst^ <> $AE) then
+ SetInstError(PInst, INVALID_GROUP_OPCODE);
+ P := PInst^.NextInst;
+ Inc(P);
+ iMod := GetModRm_Mod(P^);
+ Reg := GetModRm_Reg(P^);
+ if (iMod = $03) and (PInst^.LID.MndPrf = $F3) and (Reg < $04) then
+ begin
+ Decode_NA_ModRm(PInst);
+ Exit;
+ end;
+ Decode_Invalid_Group(PInst);
+end;
+
+procedure Decode_Group_16(PInst: PInstruction);
+var
+ P: PByte;
+ iMod, Reg: Byte;
+begin
+ SetGroup(PInst);
+ if (PInst^.OpTable <> tbTwoByte) and (PInst^.NextInst^ <> $18) then
+ SetInstError(PInst, INVALID_GROUP_OPCODE);
+ P := PInst^.NextInst;
+ Inc(P);
+ iMod := GetModRm_Mod(P^);
+ Reg := GetModRm_Reg(P^);
+ if (iMod <> $03) and (Reg < $04) then
+ begin
+ { Prefetch group instructions. }
+ Decode_NA_ModRm(PInst);
+ Exit;
+ end;
+ Decode_Invalid_Group(PInst);
+end;
+
+procedure Decode_Group_17(PInst: PInstruction);
+var
+ P: PByte;
+ Reg: Byte;
+begin
+ SetGroup(PInst);
+ P := PInst^.NextInst;
+ Inc(P);
+ Reg := GetModRm_Reg(P^);
+ if (Reg > $00) and (Reg < $04) then
+ begin
+ Decode_NA_ModRm(PInst);
+ Exit;
+ end;
+ Decode_Invalid_Group(PInst);
+end;
+
+{$ENDREGION}
+{$REGION 'DECODERS'}
+{ ========================== DECODERS PROC =============================== }
+
+procedure Decode_NA_CALL_Ap_I64(PInst: PInstruction);
+begin
+ { Instruction is only valid for x32 ! }
+ if PInst^.Archi = CPUX64 then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ PInst^.OpType := otCALL;
+ Decode_Ap(PInst);
+end;
+
+procedure Decode_NA_ModRm(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $00 }
+ if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ Decode_ModRm(PInst);
+end;
+
+procedure Decode_NA_Ib(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $00 }
+ if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ Decode_Imm(PInst, ops8bits);
+end;
+
+procedure Decode_NA_Iz(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $00 }
+ if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ Decode_Imm(PInst, PInst^.LID.zOpSize);
+end;
+
+procedure Decode_NA_I64(PInst: PInstruction);
+begin
+ { Instruction is invalid on PM64 }
+ { Only valid when mandatory prefix is : $00 }
+ if (PInst^.Archi = CPUX64) or ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+end;
+
+procedure Decode_NA(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $00 }
+ if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+end;
+
+procedure Decode_NA_ModRm_I64(PInst: PInstruction);
+begin
+ { Instruction is invalid on PM64 }
+ { Only valid when mandatory prefix is : $00 }
+ if (PInst^.Archi = CPUX64) or ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ Decode_ModRm(PInst);
+end;
+
+procedure Decode_NA_ModRm_Iz(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $00 }
+ if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ Decode_ModRm(PInst);
+ Decode_Imm(PInst, PInst^.LID.zOpSize);
+end;
+
+procedure Decode_NA_ModRm_Ib(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $00 }
+ if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ Decode_ModRm(PInst);
+ Decode_Imm(PInst, ops8bits);
+end;
+
+procedure Decode_NA_Jb_Df64(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $00 }
+ if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf <> $00)) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ PInst^.OperandFlags := opdDf64;
+ Decode_J(PInst, ops8bits);
+end;
+
+procedure Decode_NA_RET(PInst: PInstruction);
+begin
+ SetOpCode(PInst);
+ PInst^.OpType := otRET;
+ if PInst^.OpCode in [$C2, $CA] then
+ Decode_Imm(PInst, ops16bits);
+end;
+
+procedure Decode_NA_Ib_I64(PInst: PInstruction);
+begin
+ { Instruction is invalid on PM64 }
+ { Only valid when mandatory prefix is : $00 }
+ if (PInst^.Archi = CPUX64) or ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ Decode_Imm(PInst, ops8bits);
+end;
+
+procedure Decode_NA_CALL_Jz_Df64(PInst: PInstruction);
+begin
+ SetOpCode(PInst);
+ PInst^.OpType := otCALL;
+ PInst^.OperandFlags := opdDf64;
+ Decode_J(PInst, PInst^.LID.zOpSize);
+end;
+
+procedure Decode_NA_JMP_Jz_Df64(PInst: PInstruction);
+begin
+ SetOpCode(PInst);
+ PInst^.OpType := otJMP;
+ PInst^.OperandFlags := opdDf64;
+ Decode_J(PInst, PInst^.LID.zOpSize);
+end;
+
+procedure Decode_NA_JMP_Ap_I64(PInst: PInstruction);
+begin
+ if PInst^.Archi = CPUX64 then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ PInst^.OpType := otJMP;
+ Decode_Ap(PInst);
+end;
+
+procedure Decode_NA_JMP_Jb_Df64(PInst: PInstruction);
+begin
+ SetOpCode(PInst);
+ PInst^.OpType := otJMP;
+ PInst^.OperandFlags := opdDf64;
+ Decode_J(PInst, ops8bits);
+end;
+
+procedure Decode_CALL_ModRm(PInst: PInstruction);
+begin
+ PInst^.OpType := otCALL;
+ Decode_Branch_ModRm(PInst);
+end;
+
+procedure Decode_CALL_Mp(PInst: PInstruction);
+begin
+ PInst^.OpType := otCALL;
+ Decode_Mp(PInst);
+end;
+
+procedure Decode_JMP_ModRm(PInst: PInstruction);
+begin
+ PInst^.OpType := otJMP;
+ Decode_Branch_ModRm(PInst);
+end;
+
+procedure Decode_JMP_Mp(PInst: PInstruction);
+begin
+ PInst^.OpType := otJMP;
+ Decode_Mp(PInst);
+end;
+
+procedure Decode_NA_CALL(PInst: PInstruction);
+begin
+ { SYSCALL! }
+ SetOpCode(PInst);
+end;
+
+procedure Decode_NA_66_F2_F3_ModRm(PInst: PInstruction);
+begin
+ SetOpCode(PInst);
+ Decode_ModRm(PInst);
+end;
+
+procedure Decode_NA_66_ModRm(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $00 or $66 }
+ if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf in [$00, $66])) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ Decode_ModRm(PInst);
+end;
+
+procedure Decode_NA_66_F3_ModRm(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $00 or $66 or $F3 }
+ if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf = $F2)) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ Decode_ModRm(PInst);
+end;
+
+procedure Decode_NA_F3_ModRm(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $00 or $F3 }
+ if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf in [$00, $F3])) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ Decode_ModRm(PInst);
+end;
+
+procedure Decode_66_ModRm(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $66 }
+ if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $66)) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ Decode_ModRm(PInst);
+end;
+
+procedure Decode_NA_66_F2_F3_ModRm_Ib(PInst: PInstruction);
+begin
+ SetOpCode(PInst);
+ Decode_ModRm(PInst);
+ Decode_Imm(PInst, ops8bits);
+end;
+
+procedure Decode_66_F2_ModRm(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $66 or $F2 }
+ if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf in [$66, $F2])) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ Decode_ModRm(PInst);
+end;
+
+procedure Decode_F3_ModRm(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $F3 }
+ if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $F3)) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ Decode_ModRm(PInst);
+end;
+
+procedure Decode_NA_66_ModRm_Ib(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $00 or $66 }
+ if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf in [$00, $66])) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ Decode_ModRm(PInst);
+ Decode_Imm(PInst, ops8bits);
+end;
+
+procedure Decode_66_F2_F3_ModRm(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $66 or $F2 or $F3 }
+ if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf = $00)) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ Decode_ModRm(PInst);
+end;
+
+procedure Decode_F2_ModRm(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $F2 }
+ if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $F2)) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ Decode_ModRm(PInst);
+end;
+
+procedure Decode_SP_T38_F0_F7(PInst: PInstruction);
+var
+ Prf66F2: Boolean;
+begin
+ if PInst^.NextInst^ = $F3 then
+ begin
+ Decode_Group_17(PInst);
+ Exit;
+ end;
+
+ { 66 & F2 }
+ Prf66F2 := PInst^.Prefixes and (Prf_OpSize or Prf_Repne) = (Prf_OpSize or Prf_Repne);
+
+ if Prf66F2 then
+ begin
+ { Valid only for CRC32 instruction ! }
+ if (PInst^.NextInst^ = $F0) or (PInst^.NextInst^ = $F1) then
+ begin
+ Decode_NA_ModRm(PInst);
+ Exit;
+ end
+ else
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ end
+ else if PInst^.LID.MndPrf = $00 then
+ begin
+ if (PInst^.NextInst^ = $F4) or (PInst^.NextInst^ = $F6) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ end
+ else if PInst^.LID.MndPrf = $66 then
+ begin
+ if (PInst^.NextInst^ in [$F2 .. $F5]) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ end
+ else if PInst^.LID.MndPrf = $F3 then
+ begin
+ if (PInst^.NextInst^ < $F5) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ end
+ else if PInst^.LID.MndPrf = $F2 then
+ begin
+ if (PInst^.NextInst^ in [$F2 .. $F4]) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ end;
+ Decode_NA_ModRm(PInst);
+end;
+
+procedure Decode_66_ModRm_Ib(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $66 }
+ if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $66)) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ Decode_ModRm(PInst);
+ Decode_Imm(PInst, ops8bits);
+end;
+
+procedure Decode_F2_ModRm_Ib(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $F2 }
+ if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $F2)) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ Decode_ModRm(PInst);
+ Decode_Imm(PInst, ops8bits);
+end;
+
+procedure Decode_NA_RET_Iw_Df64(PInst: PInstruction);
+begin
+ PInst^.OpType := otRET;
+ SetOpCode(PInst);
+ PInst^.OperandFlags := opdDf64;
+ Decode_Imm(PInst, ops16bits);
+end;
+
+procedure Decode_NA_D64(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $00 }
+ if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf <> $00)) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ PInst^.OperandFlags := opdD64;
+end;
+
+procedure Decode_NA_Iz_D64(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $00 }
+ if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf <> $00)) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ PInst^.OperandFlags := opdD64;
+ Decode_Imm(PInst, PInst^.LID.zOpSize);
+end;
+
+procedure Decode_NA_Ib_D64(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $00 }
+ if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf <> $00)) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ PInst^.OperandFlags := opdD64;
+ Decode_Imm(PInst, ops8bits);
+end;
+
+procedure Decode_NA_RET_Df64(PInst: PInstruction);
+begin
+ PInst^.OpType := otRET;
+ PInst^.OperandFlags := opdDf64;
+ SetOpCode(PInst);
+end;
+
+procedure Decode_NA_RET_Iw(PInst: PInstruction);
+begin
+ PInst^.OpType := otRET;
+ SetOpCode(PInst);
+ Decode_Imm(PInst, ops16bits);
+end;
+
+procedure Decode_NA_Iw_Ib_D64(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $00 }
+ if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf <> $00)) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ PInst^.OperandFlags := opdD64;
+ Decode_Imm(PInst, ops16bits);
+ Decode_Imm(PInst, ops8bits);
+end;
+
+procedure Decode_NA_ModRm_F64(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $00 }
+ if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf <> $00)) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ PInst^.OperandFlags := opdF64;
+ Decode_ModRm(PInst);
+end;
+
+procedure Decode_NA_Jz_Df64(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $00 }
+ if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf <> $00)) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ PInst^.OperandFlags := opdDf64;
+ Decode_J(PInst, PInst^.LID.zOpSize);
+end;
+
+procedure Decode_NA_OfstV(PInst: PInstruction);
+begin
+ SetOpCode(PInst);
+ Decode_Imm(PInst, PInst.LID.vOpSize);
+ PInst.Disp.Value := PInst.Imm.Value;
+ PInst.Disp.Size := PInst.Imm.Size;
+ PInst.Disp.Flags := dfUsed or dfOffset;
+ PInst.Imm.Size := $00;
+ PInst.Imm.Value := $00;
+ PInst.Imm.Flags := $00;
+end;
+
+procedure Decode_NA_Iv(PInst: PInstruction);
+begin
+ { Only valid when mandatory prefix is : $00 }
+ if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then
+ begin
+ Decode_InvalidOpCode(PInst);
+ Exit;
+ end;
+ SetOpCode(PInst);
+ Decode_Imm(PInst, PInst^.LID.vOpSize);
+end;
+{$ENDREGION}
+
+function DecodeInst(PInst: PInstruction): ShortInt;
+var
+ P: PByte;
+ LArchi: Byte;
+ LAddr: PByte;
+ LErrors: Byte;
+ LVA: PByte;
+ LOptions: Byte;
+begin
+ { No Errors }
+ SetInstError(PInst, NO_ERROR);
+
+ if not(PInst^.Archi in [CPUX32, CPUX64]) then
+ SetInstError(PInst, INVALID_CPUX);
+
+ if not Assigned(PInst^.Addr) then
+ SetInstError(PInst, INVALID_ADDRESS);
+
+ { Init Instruction Structure }
+ LArchi := PInst^.Archi;
+ LAddr := PInst^.Addr;
+ LVA := PInst^.VirtualAddr;
+ LErrors := PInst^.Errors;
+ LOptions := PInst^.Options;
+
+ FillChar(PInst^, SizeOf(TInstruction), #0);
+
+ PInst^.Archi := LArchi;
+ PInst^.Addr := LAddr;
+ PInst^.Errors := LErrors;
+ PInst^.VirtualAddr := LVA;
+ PInst.Options := LOptions;
+
+ P := PInst^.Addr;
+ PInst^.NextInst := P;
+
+ PInst^.LID.zOpSize := ops32bits;
+ PInst^.LID.vOpSize := ops32bits;
+ PInst^.AddrMode := DefAddressMode[PInst^.Archi];
+
+ { Default Op Table is One Byte ! }
+ PInst^.OpTable := tbOneByte;
+
+ DecoderProcTable[OneByteTable[P^]](PInst);
+ Result := PInst^.NextInst - P;
+ PInst^.InstSize := Result;
+
+ if Result > CPUX_TO_INST_LENGTH[PInst^.Archi] then
+ SetInstError(PInst, INVALID_INSTRUCTION_LENGTH);
+end;
+
+end.
diff --git a/components/detours/Source/ModRmFlagsTables.inc b/components/detours/Source/ModRmFlagsTables.inc
new file mode 100644
index 00000000..f51efb57
--- /dev/null
+++ b/components/detours/Source/ModRmFlagsTables.inc
@@ -0,0 +1,140 @@
+// **************************************************************************************************
+// Part of Delphi Instruction Decode Library [InstDecode]
+//
+// https://github.com/MahdiSafsafi/delphi-detours-library
+
+// The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License");
+// you may not use this file except in compliance with the License. You may obtain a copy of the
+// License at http://www.mozilla.org/MPL/
+//
+// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
+// ANY KIND, either express or implied. See the License for the specific language governing rights
+// and limitations under the License.
+//
+// The Original Code is ModRmFlagsTables.inc.
+//
+// The Initial Developer of the Original Code is Mahdi Safsafi [SMP3].
+// Portions created by Mahdi Safsafi . are Copyright (C) 2013-2016 Mahdi Safsafi .
+// All Rights Reserved.
+//
+// **************************************************************************************************
+
+
+{ Reference : Intel® 64 and IA-32 Architectures Software Developer’s Manual Vol 2 }
+
+type
+ TModRmFlagsArray = array [Byte] of Byte;
+ PModRmFlagsArray = ^TModRmFlagsArray;
+ {
+ ModRMFlags :
+ Bits:4 3 2 1 0 .
+
+ Bit 0 : Set ==> Register Indirect Addressing Mode .
+ Bit 1 : Set ==> Displacement 8 bit .
+ Bit 2 : Set ==> Displacement 16 bit .
+ Bit 3 : Set ==> Displacement 32 bit.
+ Bit 4 : Set ==> SIB Used .
+
+
+ Values:
+
+ $00 ==> Register .
+ $01 ==> Register Indirect Addressing Mode with No Displacement .
+ $03 ==> Register Indirect Addressing Mode + 8 bit Displacement .
+ $04 ==> 16 bit Displacement only without register .
+ $05 ==> Register Indirect Addressing Mode + 16 bit Displacement .
+ $08 ==> 32 bit Displacement only without register .
+ $09 ==> Register Indirect Addressing Mode + 32 bit Displacement .
+ $11 ==> Register Indirect Addressing Mode + SIB .
+ $13 ==> Register Indirect Addressing Mode + SIB + 8 bit Displacement .
+ $19 ==> Register Indirect Addressing Mode + SIB + 32 bit Displacement .
+
+ }
+
+const
+
+ ModRM16Flags: TModRmFlagsArray = (
+ { => Mod=00b <= }
+ $01, $01, $01, $01, $01, $01, $04, $01, { 00 }
+ $01, $01, $01, $01, $01, $01, $04, $01, { 00 }
+ $01, $01, $01, $01, $01, $01, $04, $01, { 00 }
+ $01, $01, $01, $01, $01, $01, $04, $01, { 00 }
+ $01, $01, $01, $01, $01, $01, $04, $01, { 00 }
+ $01, $01, $01, $01, $01, $01, $04, $01, { 00 }
+ $01, $01, $01, $01, $01, $01, $04, $01, { 00 }
+ $01, $01, $01, $01, $01, $01, $04, $01, { 00 }
+ { => Mod=01b <= }
+ $03, $03, $03, $03, $03, $03, $03, $03, { 01 }
+ $03, $03, $03, $03, $03, $03, $03, $03, { 01 }
+ $03, $03, $03, $03, $03, $03, $03, $03, { 01 }
+ $03, $03, $03, $03, $03, $03, $03, $03, { 01 }
+ $03, $03, $03, $03, $03, $03, $03, $03, { 01 }
+ $03, $03, $03, $03, $03, $03, $03, $03, { 01 }
+ $03, $03, $03, $03, $03, $03, $03, $03, { 01 }
+ $03, $03, $03, $03, $03, $03, $03, $03, { 01 }
+ { => Mod=10b <= }
+ $05, $05, $05, $05, $05, $05, $05, $05, { 10 }
+ $05, $05, $05, $05, $05, $05, $05, $05, { 10 }
+ $05, $05, $05, $05, $05, $05, $05, $05, { 10 }
+ $05, $05, $05, $05, $05, $05, $05, $05, { 10 }
+ $05, $05, $05, $05, $05, $05, $05, $05, { 10 }
+ $05, $05, $05, $05, $05, $05, $05, $05, { 10 }
+ $05, $05, $05, $05, $05, $05, $05, $05, { 10 }
+ $05, $05, $05, $05, $05, $05, $05, $05, { 10 }
+ { => Mod=11b <= }
+ $00, $00, $00, $00, $00, $00, $00, $00, { 11 }
+ $00, $00, $00, $00, $00, $00, $00, $00, { 11 }
+ $00, $00, $00, $00, $00, $00, $00, $00, { 11 }
+ $00, $00, $00, $00, $00, $00, $00, $00, { 11 }
+ $00, $00, $00, $00, $00, $00, $00, $00, { 11 }
+ $00, $00, $00, $00, $00, $00, $00, $00, { 11 }
+ $00, $00, $00, $00, $00, $00, $00, $00, { 11 }
+ $00, $00, $00, $00, $00, $00, $00, $00 { 11 }
+
+ );
+ ModRM32Flags: TModRmFlagsArray = (
+ { => Mod=00b <= }
+ $01, $01, $01, $01, $11, $08, $01, $01, { 00 }
+ $01, $01, $01, $01, $11, $08, $01, $01, { 00 }
+ $01, $01, $01, $01, $11, $08, $01, $01, { 00 }
+ $01, $01, $01, $01, $11, $08, $01, $01, { 00 }
+ $01, $01, $01, $01, $11, $08, $01, $01, { 00 }
+ $01, $01, $01, $01, $11, $08, $01, $01, { 00 }
+ $01, $01, $01, $01, $11, $08, $01, $01, { 00 }
+ $01, $01, $01, $01, $11, $08, $01, $01, { 00 }
+ { => Mod=01b <= }
+ $03, $03, $03, $03, $13, $03, $03, $03, { 01 }
+ $03, $03, $03, $03, $13, $03, $03, $03, { 01 }
+ $03, $03, $03, $03, $13, $03, $03, $03, { 01 }
+ $03, $03, $03, $03, $13, $03, $03, $03, { 01 }
+ $03, $03, $03, $03, $13, $03, $03, $03, { 01 }
+ $03, $03, $03, $03, $13, $03, $03, $03, { 01 }
+ $03, $03, $03, $03, $13, $03, $03, $03, { 01 }
+ $03, $03, $03, $03, $13, $03, $03, $03, { 01 }
+ { => Mod=10b <= }
+ $09, $09, $09, $09, $19, $09, $09, $09, { 10 }
+ $09, $09, $09, $09, $19, $09, $09, $09, { 10 }
+ $09, $09, $09, $09, $19, $09, $09, $09, { 10 }
+ $09, $09, $09, $09, $19, $09, $09, $09, { 10 }
+ $09, $09, $09, $09, $19, $09, $09, $09, { 10 }
+ $09, $09, $09, $09, $19, $09, $09, $09, { 10 }
+ $09, $09, $09, $09, $19, $09, $09, $09, { 10 }
+ $09, $09, $09, $09, $19, $09, $09, $09, { 10 }
+ { => Mod=11b <= }
+ $00, $00, $00, $00, $00, $00, $00, $00, { 11 }
+ $00, $00, $00, $00, $00, $00, $00, $00, { 11 }
+ $00, $00, $00, $00, $00, $00, $00, $00, { 11 }
+ $00, $00, $00, $00, $00, $00, $00, $00, { 11 }
+ $00, $00, $00, $00, $00, $00, $00, $00, { 11 }
+ $00, $00, $00, $00, $00, $00, $00, $00, { 11 }
+ $00, $00, $00, $00, $00, $00, $00, $00, { 11 }
+ $00, $00, $00, $00, $00, $00, $00, $00 { 11 }
+
+ );
+
+ ModRmFlags: array [0 .. 3] of PModRmFlagsArray = ( //
+ nil,
+ @ModRM16Flags, { AddrMode 16-bits }
+ @ModRM32Flags, { AddrMode 32-bits }
+ @ModRM32Flags { AddrMode 64-bits }
+ );
\ No newline at end of file
diff --git a/components/detours/Source/OpCodesTables.inc b/components/detours/Source/OpCodesTables.inc
new file mode 100644
index 00000000..2a46dc94
--- /dev/null
+++ b/components/detours/Source/OpCodesTables.inc
@@ -0,0 +1,1158 @@
+// **************************************************************************************************
+// Part of Delphi Instruction Decode Library [InstDecode]
+//
+// https://github.com/MahdiSafsafi/delphi-detours-library
+
+// The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License");
+// you may not use this file except in compliance with the License. You may obtain a copy of the
+// License at http://www.mozilla.org/MPL/
+//
+// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
+// ANY KIND, either express or implied. See the License for the specific language governing rights
+// and limitations under the License.
+//
+// The Original Code is OpCodesTables.inc.
+//
+// The Initial Developer of the Original Code is Mahdi Safsafi [SMP3].
+// Portions created by Mahdi Safsafi . are Copyright (C) 2013-2016 Mahdi Safsafi .
+// All Rights Reserved.
+//
+// **************************************************************************************************
+
+{ Reference :
+ -sandpile.org
+ -Intel® 64 and IA-32 Architectures Software Developer’s Manual Vol 2
+}
+
+{ ============================================
+ Index -> DecoderProc
+ ============================================ }
+{ 00 = Decode_InvalidOpCode}
+{ 01 = Decode_NA_ModRm}
+{ 02 = Decode_NA_Ib}
+{ 03 = Decode_NA_Iz}
+{ 04 = Decode_NA_I64}
+{ 05 = Decode_Escape_2_Byte}
+{ 06 = Decode_ES_Prefix}
+{ 07 = Decode_CS_Prefix}
+{ 08 = Decode_SS_Prefix}
+{ 09 = Decode_DS_Prefix}
+{ 10 = Decode_REX_Prefix}
+{ 11 = Decode_NA_D64}
+{ 12 = Decode_NA_ModRm_I64}
+{ 13 = Decode_FS_Prefix}
+{ 14 = Decode_GS_Prefix}
+{ 15 = Decode_OPSIZE_Prefix}
+{ 16 = Decode_ADSIZE_Prefix}
+{ 17 = Decode_NA_Iz_D64}
+{ 18 = Decode_NA_ModRm_Iz}
+{ 19 = Decode_NA_Ib_D64}
+{ 20 = Decode_NA_ModRm_Ib}
+{ 21 = Decode_NA}
+{ 22 = Decode_NA_Jb_Df64}
+{ 23 = Decode_Group_1}
+{ 24 = Decode_Group_1A}
+{ 25 = Decode_NA_CALL_Ap_I64}
+{ 26 = Decode_NA_OfstV}
+{ 27 = Decode_NA_Iv}
+{ 28 = Decode_Group_2}
+{ 29 = Decode_NA_RET_Iw_Df64}
+{ 30 = Decode_NA_RET_Df64}
+{ 31 = Decode_VEX3_Prefix}
+{ 32 = Decode_VEX2_Prefix}
+{ 33 = Decode_Group_11}
+{ 34 = Decode_NA_Iw_Ib_D64}
+{ 35 = Decode_NA_RET_Iw}
+{ 36 = Decode_NA_RET}
+{ 37 = Decode_NA_Ib_I64}
+{ 38 = Decode_Escape_FPU_D8}
+{ 39 = Decode_Escape_FPU_D9}
+{ 40 = Decode_Escape_FPU_DA}
+{ 41 = Decode_Escape_FPU_DB}
+{ 42 = Decode_Escape_FPU_DC}
+{ 43 = Decode_Escape_FPU_DD}
+{ 44 = Decode_Escape_FPU_DE}
+{ 45 = Decode_Escape_FPU_DF}
+{ 46 = Decode_NA_CALL_Jz_Df64}
+{ 47 = Decode_NA_JMP_Jz_Df64}
+{ 48 = Decode_NA_JMP_Ap_I64}
+{ 49 = Decode_NA_JMP_Jb_Df64}
+{ 50 = Decode_LOCK_Prefix}
+{ 51 = Decode_REPNE_Prefix}
+{ 52 = Decode_REPE_Prefix}
+{ 53 = Decode_Group_3}
+{ 54 = Decode_Group_4_INC_DEC}
+{ 55 = Decode_Group_5_INC_DEC}
+{ 56 = Decode_Group_6}
+{ 57 = Decode_Group_7}
+{ 58 = Decode_NA_CALL}
+{ 59 = Decode_NA_66_F2_F3_ModRm}
+{ 60 = Decode_NA_66_ModRm}
+{ 61 = Decode_NA_66_F3_ModRm}
+{ 62 = Decode_Group_16}
+{ 63 = Decode_NA_ModRm_F64}
+{ 64 = Decode_Escape_3_Byte}
+{ 65 = Decode_NA_F3_ModRm}
+{ 66 = Decode_66_ModRm}
+{ 67 = Decode_NA_66_F2_F3_ModRm_Ib}
+{ 68 = Decode_Group_12}
+{ 69 = Decode_Group_13}
+{ 70 = Decode_Group_14}
+{ 71 = Decode_66_F2_ModRm}
+{ 72 = Decode_NA_Jz_Df64}
+{ 73 = Decode_Group_15}
+{ 74 = Decode_F3_ModRm}
+{ 75 = Decode_Group_10_UD2}
+{ 76 = Decode_Group_8}
+{ 77 = Decode_NA_66_ModRm_Ib}
+{ 78 = Decode_Group_9}
+{ 79 = Decode_66_F2_F3_ModRm}
+{ 80 = Decode_F2_ModRm}
+{ 81 = Decode_SP_T38_F0_F7}
+{ 82 = Decode_66_ModRm_Ib}
+{ 83 = Decode_F2_ModRm_Ib}
+
+{============================================
+ OneByteTable
+============================================}
+const OneByteTable : array[Byte] of Byte =(//
+{0x00} 01, {ADD}
+{0x01} 01, {ADD}
+{0x02} 01, {ADD}
+{0x03} 01, {ADD}
+{0x04} 02, {ADD}
+{0x05} 03, {ADD}
+{0x06} 04, {PUSH}
+{0x07} 04, {POP}
+{0x08} 01, {OR}
+{0x09} 01, {OR}
+{0x0A} 01, {OR}
+{0x0B} 01, {OR}
+{0x0C} 02, {OR}
+{0x0D} 03, {OR}
+{0x0E} 04, {PUSH}
+{0x0F} 05, {Escape_2_Byte}
+{0x10} 01, {ADC}
+{0x11} 01, {ADC}
+{0x12} 01, {ADC}
+{0x13} 01, {ADC}
+{0x14} 02, {ADC}
+{0x15} 03, {ADC}
+{0x16} 04, {PUSH}
+{0x17} 04, {POP}
+{0x18} 01, {SBB}
+{0x19} 01, {SBB}
+{0x1A} 01, {SBB}
+{0x1B} 01, {SBB}
+{0x1C} 02, {SBB}
+{0x1D} 03, {SBB}
+{0x1E} 04, {PUSH}
+{0x1F} 04, {POP}
+{0x20} 01, {AND}
+{0x21} 01, {AND}
+{0x22} 01, {AND}
+{0x23} 01, {AND}
+{0x24} 02, {AND}
+{0x25} 03, {AND}
+{0x26} 06, {ES_Prefix}
+{0x27} 04, {DAA}
+{0x28} 01, {SUB}
+{0x29} 01, {SUB}
+{0x2A} 01, {SUB}
+{0x2B} 01, {SUB}
+{0x2C} 02, {SUB}
+{0x2D} 03, {SUB}
+{0x2E} 07, {CS_Prefix}
+{0x2F} 04, {DAS}
+{0x30} 01, {XOR}
+{0x31} 01, {XOR}
+{0x32} 01, {XOR}
+{0x33} 01, {XOR}
+{0x34} 02, {XOR}
+{0x35} 03, {XOR}
+{0x36} 08, {SS_Prefix}
+{0x37} 04, {AAA}
+{0x38} 01, {CMP}
+{0x39} 01, {CMP}
+{0x3A} 01, {CMP}
+{0x3B} 01, {CMP}
+{0x3C} 02, {CMP}
+{0x3D} 03, {CMP}
+{0x3E} 09, {DS_Prefix}
+{0x3F} 04, {AAS}
+{0x40} 10, {INC/REX_Prefix}
+{0x41} 10, {INC/REX_Prefix}
+{0x42} 10, {INC/REX_Prefix}
+{0x43} 10, {INC/REX_Prefix}
+{0x44} 10, {INC/REX_Prefix}
+{0x45} 10, {INC/REX_Prefix}
+{0x46} 10, {INC/REX_Prefix}
+{0x47} 10, {INC/REX_Prefix}
+{0x48} 10, {DEC/REX_Prefix}
+{0x49} 10, {DEC/REX_Prefix}
+{0x4A} 10, {DEC/REX_Prefix}
+{0x4B} 10, {DEC/REX_Prefix}
+{0x4C} 10, {DEC/REX_Prefix}
+{0x4D} 10, {DEC/REX_Prefix}
+{0x4E} 10, {DEC/REX_Prefix}
+{0x4F} 10, {DEC/REX_Prefix}
+{0x50} 11, {PUSH}
+{0x51} 11, {PUSH}
+{0x52} 11, {PUSH}
+{0x53} 11, {PUSH}
+{0x54} 11, {PUSH}
+{0x55} 11, {PUSH}
+{0x56} 11, {PUSH}
+{0x57} 11, {PUSH}
+{0x58} 11, {POP}
+{0x59} 11, {POP}
+{0x5A} 11, {POP}
+{0x5B} 11, {POP}
+{0x5C} 11, {POP}
+{0x5D} 11, {POP}
+{0x5E} 11, {POP}
+{0x5F} 11, {POP}
+{0x60} 04, {PUSHAD/PUSHA}
+{0x61} 04, {POPAD/POPA}
+{0x62} 12, {BOUND}
+{0x63} 01, {ARPL/MOVSXD}
+{0x64} 13, {FS_Prefix}
+{0x65} 14, {GS_Prefix}
+{0x66} 15, {OPSIZE_Prefix}
+{0x67} 16, {ADSIZE_Prefix}
+{0x68} 17, {PUSH}
+{0x69} 18, {IMUL}
+{0x6A} 19, {PUSH}
+{0x6B} 20, {IMUL}
+{0x6C} 21, {INS}
+{0x6D} 21, {INS}
+{0x6E} 21, {OUTS}
+{0x6F} 21, {OUTS}
+{0x70} 22, {JO}
+{0x71} 22, {JNO}
+{0x72} 22, {JB}
+{0x73} 22, {JNB}
+{0x74} 22, {JZ}
+{0x75} 22, {JNZ}
+{0x76} 22, {JBE}
+{0x77} 22, {JNBE}
+{0x78} 22, {JS}
+{0x79} 22, {JNS}
+{0x7A} 22, {JP}
+{0x7B} 22, {JNP}
+{0x7C} 22, {JL}
+{0x7D} 22, {JNL}
+{0x7E} 22, {JLE}
+{0x7F} 22, {JNLE}
+{0x80} 23, {group_1}
+{0x81} 23, {group_1}
+{0x82} 23, {group_1*}
+{0x83} 23, {group_1}
+{0x84} 01, {TEST}
+{0x85} 01, {TEST}
+{0x86} 01, {XCHG}
+{0x87} 01, {XCHG}
+{0x88} 01, {MOV}
+{0x89} 01, {MOV}
+{0x8A} 01, {MOV}
+{0x8B} 01, {MOV}
+{0x8C} 01, {MOV}
+{0x8D} 01, {LEA}
+{0x8E} 01, {MOV}
+{0x8F} 24, {group_1A}
+{0x90} 21, {PAUSE/NOP}
+{0x91} 21, {XCHG}
+{0x92} 21, {XCHG}
+{0x93} 21, {XCHG}
+{0x94} 21, {XCHG}
+{0x95} 21, {XCHG}
+{0x96} 21, {XCHG}
+{0x97} 21, {XCHG}
+{0x98} 21, {CWDE/CBW/CDQE}
+{0x99} 21, {CDQ/CWD/CQO}
+{0x9A} 25, {CALL}
+{0x9B} 21, {WAIT}
+{0x9C} 11, {PUSHF}
+{0x9D} 11, {POPF}
+{0x9E} 21, {SAHF}
+{0x9F} 21, {LAHF}
+{0xA0} 26, {MOV}
+{0xA1} 26, {MOV}
+{0xA2} 26, {MOV}
+{0xA3} 26, {MOV}
+{0xA4} 21, {MOVS}
+{0xA5} 21, {MOVS}
+{0xA6} 21, {CMPS}
+{0xA7} 21, {CMPS}
+{0xA8} 02, {TEST}
+{0xA9} 03, {TEST}
+{0xAA} 21, {STOS}
+{0xAB} 21, {STOS}
+{0xAC} 21, {LODS}
+{0xAD} 21, {LODS}
+{0xAE} 21, {SCAS}
+{0xAF} 21, {SCAS}
+{0xB0} 02, {MOV}
+{0xB1} 02, {MOV}
+{0xB2} 02, {MOV}
+{0xB3} 02, {MOV}
+{0xB4} 02, {MOV}
+{0xB5} 02, {MOV}
+{0xB6} 02, {MOV}
+{0xB7} 02, {MOV}
+{0xB8} 27, {MOV}
+{0xB9} 27, {MOV}
+{0xBA} 27, {MOV}
+{0xBB} 27, {MOV}
+{0xBC} 27, {MOV}
+{0xBD} 27, {MOV}
+{0xBE} 27, {MOV}
+{0xBF} 27, {MOV}
+{0xC0} 28, {group_2}
+{0xC1} 28, {group_2}
+{0xC2} 29, {RET}
+{0xC3} 30, {RET}
+{0xC4} 31, {LES/VEX3_Prefix}
+{0xC5} 32, {LDS/VEX2_Prefix}
+{0xC6} 33, {group_11}
+{0xC7} 33, {group_11}
+{0xC8} 34, {ENTER}
+{0xC9} 11, {LEAVE}
+{0xCA} 35, {RET}
+{0xCB} 36, {RET}
+{0xCC} 21, {INT3}
+{0xCD} 02, {INT}
+{0xCE} 04, {INTO}
+{0xCF} 36, {IRET}
+{0xD0} 28, {group_2}
+{0xD1} 28, {group_2}
+{0xD2} 28, {group_2}
+{0xD3} 28, {group_2}
+{0xD4} 37, {AAM}
+{0xD5} 37, {AAD}
+{0xD6} 04, {SETALC}
+{0xD7} 21, {XLAT}
+{0xD8} 38, {Escape_FPU_D8}
+{0xD9} 39, {Escape_FPU_D9}
+{0xDA} 40, {Escape_FPU_DA}
+{0xDB} 41, {Escape_FPU_DB}
+{0xDC} 42, {Escape_FPU_DC}
+{0xDD} 43, {Escape_FPU_DD}
+{0xDE} 44, {Escape_FPU_DE}
+{0xDF} 45, {Escape_FPU_DF}
+{0xE0} 22, {LOOPNZ/LOOPNE}
+{0xE1} 22, {LOOPZ/LOOPE}
+{0xE2} 22, {LOOP}
+{0xE3} 22, {JRCX/JECX/JCXZ}
+{0xE4} 02, {IN}
+{0xE5} 02, {IN}
+{0xE6} 02, {OUT}
+{0xE7} 02, {OUT}
+{0xE8} 46, {CALL}
+{0xE9} 47, {JMP}
+{0xEA} 48, {JMP}
+{0xEB} 49, {JMP}
+{0xEC} 21, {IN}
+{0xED} 21, {IN}
+{0xEE} 21, {OUT}
+{0xEF} 21, {OUT}
+{0xF0} 50, {LOCK_Prefix}
+{0xF1} 21, {INT1}
+{0xF2} 51, {REPNE_Prefix}
+{0xF3} 52, {REPE_Prefix}
+{0xF4} 21, {HLT}
+{0xF5} 21, {CMC}
+{0xF6} 53, {group_3}
+{0xF7} 53, {group_3}
+{0xF8} 21, {CLC}
+{0xF9} 21, {STC}
+{0xFA} 21, {CLI}
+{0xFB} 21, {STI}
+{0xFC} 21, {CLD}
+{0xFD} 21, {STD}
+{0xFE} 54, {group_4_INC_DEC}
+{0xFF} 55 {group_5_INC_DEC}
+);
+{============================================
+ TwoByteTable
+============================================}
+const TwoByteTable : array[Byte] of Byte =(//
+{0x00} 56, {group_6}
+{0x01} 57, {group_7}
+{0x02} 01, {LAR}
+{0x03} 01, {LSL}
+{0x04} 21, {LOADALL?/RESET?/HANG?}
+{0x05} 58, {LOADALL/SYSCALL}
+{0x06} 21, {CLTS}
+{0x07} 36, {LOADALL/SYSRET}
+{0x08} 21, {INVD}
+{0x09} 21, {WBINVD}
+{0x0A} 21, {CL1INVMB}
+{0x0B} 21, {UD1}
+{0x0C} 00, {InvalidOpCode}
+{0x0D} 21, {3DNow}
+{0x0E} 21, {3DNow}
+{0x0F} 21, {3DNow}
+{0x10} 59, {VMOVUPD/VMOVSD/VMOVSS/VMOVUPS}
+{0x11} 59, {VMOVUPD/VMOVSD/VMOVSS/VMOVUPS}
+{0x12} 59, {VMOVLPD/VMOVDDUP/VMOVSLDUP/VMOVLPS/VMOVHLPS}
+{0x13} 60, {InvalidOpCode/VMOVLPD/VMOVLPS}
+{0x14} 60, {InvalidOpCode/VUNPCKLPD/VUNPCKLPS}
+{0x15} 60, {InvalidOpCode/VUNPCKHPD/VUNPCKHPS}
+{0x16} 61, {InvalidOpCode/VMOVHPD/VMOVSHDUP/VMOVLHPS/VMOVHPS}
+{0x17} 60, {InvalidOpCode/VMOVHPD/VMOVHPS}
+{0x18} 62, {group_16}
+{0x19} 62, {group_16}
+{0x1A} 62, {group_16}
+{0x1B} 62, {group_16}
+{0x1C} 62, {group_16}
+{0x1D} 62, {group_16}
+{0x1E} 62, {group_16}
+{0x1F} 62, {group_16}
+{0x20} 63, {MOV}
+{0x21} 63, {MOV}
+{0x22} 63, {MOV}
+{0x23} 63, {MOV}
+{0x24} 63, {MOV}
+{0x25} 00, {InvalidOpCode}
+{0x26} 63, {MOV}
+{0x27} 00, {InvalidOpCode}
+{0x28} 60, {InvalidOpCode/VMOVAPD/VMOVAPS}
+{0x29} 60, {InvalidOpCode/VMOVAPD/VMOVAPS}
+{0x2A} 59, {VCVTSI2SD/CVTPI2PD/VCVTSI2SS/CVTPI2PS}
+{0x2B} 59, {MOVNTSD/MOVNTSS/VMOVNTPD/VMOVNTPS}
+{0x2C} 59, {CVTTPD2PI/VCVTTSD2SI/CVTTPS2PI/VCVTTSS2SI}
+{0x2D} 59, {CVTPD2PI/VCVTSD2SI/CVTPS2PI/VCVTSS2SI}
+{0x2E} 60, {InvalidOpCode/VUCOMISD/VUCOMISS}
+{0x2F} 60, {InvalidOpCode/VCOMISD/VCOMISS}
+{0x30} 21, {WRMSR}
+{0x31} 21, {RDTSC}
+{0x32} 21, {RDMSR}
+{0x33} 21, {RDPMC}
+{0x34} 21, {SYSENTER}
+{0x35} 21, {SYSEXIT}
+{0x36} 00, {InvalidOpCode}
+{0x37} 21, {GETSEC}
+{0x38} 64, {Escape_3_Byte}
+{0x39} 00, {InvalidOpCode}
+{0x3A} 64, {Escape_3_Byte}
+{0x3B} 00, {InvalidOpCode}
+{0x3C} 00, {InvalidOpCode}
+{0x3D} 00, {InvalidOpCode}
+{0x3E} 00, {InvalidOpCode}
+{0x3F} 00, {InvalidOpCode}
+{0x40} 01, {CMOVO}
+{0x41} 01, {CMOVNO}
+{0x42} 01, {CMOVB}
+{0x43} 01, {CMOVNB}
+{0x44} 01, {CMOVZ}
+{0x45} 01, {CMOVNZ}
+{0x46} 01, {CMOVBE}
+{0x47} 01, {CMOVNBE}
+{0x48} 01, {CMOVS}
+{0x49} 01, {CMOVNS}
+{0x4A} 01, {CMOVP}
+{0x4B} 01, {CMOVNP}
+{0x4C} 01, {CMOVL}
+{0x4D} 01, {CMOVNL}
+{0x4E} 01, {CMOVLE}
+{0x4F} 01, {CMOVNLE}
+{0x50} 60, {InvalidOpCode/VMOVMSKPD/VMOVMSKPS}
+{0x51} 59, {VSQRTPD/VSQRTSD/VSQRTSS/VSQRTPS}
+{0x52} 65, {InvalidOpCode/VRSQRTSS/VRSQRTPS}
+{0x53} 65, {InvalidOpCode/VRCPSS/VRCPPS}
+{0x54} 60, {InvalidOpCode/VANDPD/VANDPS}
+{0x55} 60, {InvalidOpCode/VANDNPD/VANDNPS}
+{0x56} 60, {InvalidOpCode/VORPD/VORPS}
+{0x57} 60, {InvalidOpCode/VXORPD/VXORPS}
+{0x58} 59, {VADDPD/VADDSD/VADDSS/VADDPS}
+{0x59} 59, {VMULPD/VMULSD/VMULSS/VMULPS}
+{0x5A} 59, {VCVTPD2PS/VCVTSD2SS/VCVTSS2SD/VCVTPS2PD}
+{0x5B} 61, {InvalidOpCode/VCVTPS2DQ/VCVTTPS2DQ/VCVTDQ2PS}
+{0x5C} 59, {VSUBPD/VSUBSD/VSUBSS/VSUBPS}
+{0x5D} 59, {VMINPD/VMINSD/VMINSS/VMINPS}
+{0x5E} 59, {VDIVPD/VDIVSD/VDIVSS/VDIVPS}
+{0x5F} 59, {VMAXPD/VMAXSD/VMAXSS/VMAXPS}
+{0x60} 60, {PUNPCKLBW/VPUNPCKLBW}
+{0x61} 60, {PUNPCKLWD/VPUNPCKLWD}
+{0x62} 60, {PUNPCKLDQ/VPUNPCKLDQ}
+{0x63} 60, {PACKSSWB/VPACKSSWB}
+{0x64} 60, {PCMPGTB/VPCMPGTB}
+{0x65} 60, {PCMPGTW/VPCMPGTW}
+{0x66} 60, {PCMPGTD/VPCMPGTD}
+{0x67} 60, {PACKUSWB/VPACKUSWB}
+{0x68} 60, {PUNPCKHBW/InvalidOpCode/VPUNPCKHBW}
+{0x69} 60, {PUNPCKHWD/InvalidOpCode/VPUNPCKHWD}
+{0x6A} 60, {PUNPCKHDQ/InvalidOpCode/VPUNPCKHDQ}
+{0x6B} 60, {PACKSSDW/InvalidOpCode/VPACKSSDW}
+{0x6C} 66, {InvalidOpCode/VPUNPCKLQDQ}
+{0x6D} 66, {InvalidOpCode/VPUNPCKHQDQ}
+{0x6E} 60, {MOVDQ/InvalidOpCode/VMOVDQ}
+{0x6F} 61, {MOVQ/InvalidOpCode/VMOVDQA/VMOVDQU}
+{0x70} 67, {VPSHUFD/VPSHUFLW/VPSHUFHW/PSHUFW}
+{0x71} 68, {group_12}
+{0x72} 69, {group_13}
+{0x73} 70, {group_14}
+{0x74} 60, {PCMPEQB/InvalidOpCode/VPCMPEQB}
+{0x75} 60, {PCMPEQW/InvalidOpCode/VPCMPEQW}
+{0x76} 60, {PCMPEQD/InvalidOpCode/VPCMPEQD}
+{0x77} 21, {EMMS/VZEROUPPER/VZEROALL/InvalidOpCode}
+{0x78} 01, {VMREAD/InvalidOpCode}
+{0x79} 01, {VMWRITE/InvalidOpCode}
+{0x7A} 21, {SSE5A/InvalidOpCode}
+{0x7B} 21, {SSE5A/InvalidOpCode}
+{0x7C} 71, {InvalidOpCode/VHADDPD/VHADDPS}
+{0x7D} 71, {InvalidOpCode/VHSUBPD/VHSUBPS}
+{0x7E} 61, {MOVDQ/InvalidOpCode/VMOVDQ/VMOVQ}
+{0x7F} 61, {MOVQ/InvalidOpCode/VMOVDQA/VMOVDQU}
+{0x80} 72, {JO}
+{0x81} 72, {JNO}
+{0x82} 72, {JB}
+{0x83} 72, {JNB}
+{0x84} 72, {JZ}
+{0x85} 72, {JNZ}
+{0x86} 72, {JBE}
+{0x87} 72, {JNBE}
+{0x88} 72, {JS}
+{0x89} 72, {JNS}
+{0x8A} 72, {JP}
+{0x8B} 72, {JNP}
+{0x8C} 72, {JL}
+{0x8D} 72, {JNL}
+{0x8E} 72, {JLE}
+{0x8F} 72, {JNLE}
+{0x90} 01, {SETO}
+{0x91} 01, {SETNO}
+{0x92} 01, {SETB}
+{0x93} 01, {SETNB}
+{0x94} 01, {SETZ}
+{0x95} 01, {SETNZ}
+{0x96} 01, {SETBE}
+{0x97} 01, {SETNBE}
+{0x98} 01, {SETS}
+{0x99} 01, {SETNS}
+{0x9A} 01, {SETP}
+{0x9B} 01, {SETNP}
+{0x9C} 01, {SETL}
+{0x9D} 01, {SETNL}
+{0x9E} 01, {SETLE}
+{0x9F} 01, {SETNLE}
+{0xA0} 11, {PUSH}
+{0xA1} 11, {POP}
+{0xA2} 21, {CPUID}
+{0xA3} 01, {BT}
+{0xA4} 20, {SHLD}
+{0xA5} 01, {SHLD}
+{0xA6} 00, {InvalidOpCode}
+{0xA7} 00, {InvalidOpCode}
+{0xA8} 11, {PUSH}
+{0xA9} 11, {POP}
+{0xAA} 21, {RSM}
+{0xAB} 01, {BTS}
+{0xAC} 20, {SHRD}
+{0xAD} 01, {SHRD}
+{0xAE} 73, {group_15}
+{0xAF} 01, {IMUL}
+{0xB0} 01, {CMPXCHG}
+{0xB1} 01, {CMPXCHG}
+{0xB2} 01, {LSS}
+{0xB3} 01, {BTR}
+{0xB4} 01, {LFS}
+{0xB5} 01, {LGS}
+{0xB6} 01, {MOVZX}
+{0xB7} 01, {MOVZX}
+{0xB8} 74, {POPCNT/InvalidOpCode}
+{0xB9} 75, {group_10_UD2/InvalidOpCode}
+{0xBA} 76, {group_8/InvalidOpCode}
+{0xBB} 01, {BTC/InvalidOpCode}
+{0xBC} 65, {BSF/TZCNT}
+{0xBD} 65, {BSR/LZCNT}
+{0xBE} 01, {MOVSX/InvalidOpCode}
+{0xBF} 01, {MOVSX/InvalidOpCode}
+{0xC0} 59, {XADD}
+{0xC1} 59, {XADD}
+{0xC2} 67, {VCMPccPD/VCMPccSD/VCMPccSS/VCMPccPS}
+{0xC3} 01, {InvalidOpCode/MOVNTI}
+{0xC4} 77, {InvalidOpCode/VPINSRW/PINSRW}
+{0xC5} 77, {InvalidOpCode/VPEXTRW/PEXTRW}
+{0xC6} 77, {InvalidOpCode/VSHUFPD/VSHUFPS}
+{0xC7} 78, {group_9}
+{0xC8} 21, {BSWAP}
+{0xC9} 21, {BSWAP}
+{0xCA} 21, {BSWAP}
+{0xCB} 21, {BSWAP}
+{0xCC} 21, {BSWAP}
+{0xCD} 21, {BSWAP}
+{0xCE} 21, {BSWAP}
+{0xCF} 21, {BSWAP}
+{0xD0} 71, {InvalidOpCode/VADDSUBPD/VADDSUBPS}
+{0xD1} 60, {PSRLW/InvalidOpCode/VPSRLW}
+{0xD2} 60, {PSRLD/InvalidOpCode/VPSRLD}
+{0xD3} 60, {PSRLQ/InvalidOpCode/VPSRLQ}
+{0xD4} 60, {InvalidOpCode/VPADDQ/PADDQ}
+{0xD5} 60, {PMULLW/InvalidOpCode/VPMULLW}
+{0xD6} 79, {InvalidOpCode/MOVDQ2Q/MOVQ2DQ/VMOVQ}
+{0xD7} 60, {InvalidOpCode/VPMOVMSKB/PMOVMSKB}
+{0xD8} 60, {PSUBUSB/VPSUBUSB}
+{0xD9} 60, {PSUBUSW/VPSUBUSW}
+{0xDA} 60, {VPMINUB/PMINUB}
+{0xDB} 60, {PAND/VPAND}
+{0xDC} 60, {PADDUSB/VPADDUSB}
+{0xDD} 60, {PADDUSW/VPADDUSW}
+{0xDE} 60, {VPMAXUB/PMAXUB}
+{0xDF} 60, {PANDN/VPANDN}
+{0xE0} 60, {InvalidOpCode/VPAVGB/PAVGB}
+{0xE1} 60, {PSRAW/InvalidOpCode/VPSRAW}
+{0xE2} 60, {PSRAD/InvalidOpCode/VPSRAD}
+{0xE3} 60, {InvalidOpCode/VPAVGW/PAVGW}
+{0xE4} 60, {InvalidOpCode/VPMULHUW/PMULHUW}
+{0xE5} 60, {PMULHW/InvalidOpCode/VPMULHW}
+{0xE6} 79, {InvalidOpCode/VCVTTPD2DQ/VCVTPD2DQ/VCVTDQ2PD}
+{0xE7} 60, {InvalidOpCode/VMOVNTDQ/MOVNTQ}
+{0xE8} 60, {PSUBSB/VPSUBSB}
+{0xE9} 60, {PSUBSW/VPSUBSW}
+{0xEA} 60, {VPMINSW/PMINSW}
+{0xEB} 60, {POR/VPOR}
+{0xEC} 60, {PADDSB/VPADDSB}
+{0xED} 60, {PADDSW/VPADDSW}
+{0xEE} 60, {VPMAXSW/PMAXSW}
+{0xEF} 60, {PXOR/VPXOR}
+{0xF0} 80, {InvalidOpCode/VLDDQU}
+{0xF1} 60, {PSLLW/InvalidOpCode/VPSLLW}
+{0xF2} 60, {PSLLD/InvalidOpCode/VPSLLD}
+{0xF3} 60, {PSLLQ/InvalidOpCode/VPSLLQ}
+{0xF4} 60, {InvalidOpCode/VPMULUDQ/PMULUDQ}
+{0xF5} 60, {PMADDWD/InvalidOpCode/VPMADDWD}
+{0xF6} 60, {InvalidOpCode/VPSADBW/PSADBW}
+{0xF7} 60, {InvalidOpCode/VMASKMOVDQU/MASKMOVQ}
+{0xF8} 60, {PSUBB/VPSUBB}
+{0xF9} 60, {PSUBW/VPSUBW}
+{0xFA} 60, {PSUBD/VPSUBD}
+{0xFB} 60, {VPSUBQ/PSUBQ}
+{0xFC} 60, {PADDB/VPADDB}
+{0xFD} 60, {PADDW/VPADDW}
+{0xFE} 60, {PADDD/VPADDD}
+{0xFF} 00 {InvalidOpCode}
+);
+{============================================
+ ThreeByteTable38
+============================================}
+const ThreeByteTable38 : array[Byte] of Byte =(//
+{0x00} 60, {VPSHUFB/PSHUFB}
+{0x01} 60, {VPHADDW/PHADDW}
+{0x02} 60, {VPHADDD/PHADDD}
+{0x03} 60, {VPHADDSW/PHADDSW}
+{0x04} 60, {VPMADDUBSW/PMADDUBSW}
+{0x05} 60, {VPHSUBW/PHSUBW}
+{0x06} 60, {VPHSUBD/PHSUBD}
+{0x07} 60, {VPHSUBSW/PHSUBSW}
+{0x08} 60, {VPSIGNB/PSIGNB}
+{0x09} 60, {VPSIGNW/PSIGNW}
+{0x0A} 60, {VPSIGND/PSIGND}
+{0x0B} 60, {VPMULHRSW/PMULHRSW}
+{0x0C} 66, {VPERMILPS/InvalidOpCode}
+{0x0D} 66, {VPERMILPD/InvalidOpCode}
+{0x0E} 66, {VTESTPS/InvalidOpCode}
+{0x0F} 66, {VTESTPD/InvalidOpCode}
+{0x10} 66, {InvalidOpCode/PBLENDVB}
+{0x11} 00, {InvalidOpCode}
+{0x12} 00, {InvalidOpCode}
+{0x13} 66, {VCVTPH2PS/InvalidOpCode}
+{0x14} 66, {InvalidOpCode/BLENDVPS}
+{0x15} 66, {InvalidOpCode/BLENDVPD}
+{0x16} 66, {VPERMPS/InvalidOpCode}
+{0x17} 66, {InvalidOpCode/VPTEST}
+{0x18} 66, {VBROADCASTSS/InvalidOpCode}
+{0x19} 66, {VBROADCASTSD/InvalidOpCode}
+{0x1A} 66, {VBROADCASTF128/InvalidOpCode}
+{0x1B} 00, {InvalidOpCode}
+{0x1C} 60, {VPABSB/PABSB}
+{0x1D} 60, {VPABSW/PABSW}
+{0x1E} 60, {VPABSD/PABSD}
+{0x1F} 00, {InvalidOpCode}
+{0x20} 66, {InvalidOpCode/VPMOVSXBW}
+{0x21} 66, {InvalidOpCode/VPMOVSXBD}
+{0x22} 66, {InvalidOpCode/VPMOVSXBQ}
+{0x23} 66, {InvalidOpCode/VPMOVSXWD}
+{0x24} 66, {InvalidOpCode/VPMOVSXWQ}
+{0x25} 66, {InvalidOpCode/VPMOVSXDQ}
+{0x26} 00, {InvalidOpCode}
+{0x27} 00, {InvalidOpCode}
+{0x28} 66, {InvalidOpCode/VPMULDQ}
+{0x29} 66, {InvalidOpCode/VPCMPEQQ}
+{0x2A} 66, {InvalidOpCode/VMOVNTDQA}
+{0x2B} 66, {InvalidOpCode/VPACKUSDW}
+{0x2C} 66, {VMASKMOVPS/InvalidOpCode}
+{0x2D} 66, {VMASKMOVPD/InvalidOpCode}
+{0x2E} 66, {VMASKMOVPS/InvalidOpCode}
+{0x2F} 66, {VMASKMOVPD/InvalidOpCode}
+{0x30} 66, {InvalidOpCode/VPMOVZXBW}
+{0x31} 66, {InvalidOpCode/VPMOVZXBD}
+{0x32} 66, {InvalidOpCode/VPMOVZXBQ}
+{0x33} 66, {InvalidOpCode/VPMOVZXWD}
+{0x34} 66, {InvalidOpCode/VPMOVZXWQ}
+{0x35} 66, {InvalidOpCode/VPMOVZXDQ}
+{0x36} 66, {VPERMD/InvalidOpCode}
+{0x37} 66, {InvalidOpCode/VPCMPGTQ}
+{0x38} 66, {InvalidOpCode/VPMINSB}
+{0x39} 66, {InvalidOpCode/VPMINSD}
+{0x3A} 66, {InvalidOpCode/VPMINUW}
+{0x3B} 66, {InvalidOpCode/VPMINUD}
+{0x3C} 66, {InvalidOpCode/VPMAXSB}
+{0x3D} 66, {InvalidOpCode/VPMAXSD}
+{0x3E} 66, {InvalidOpCode/VPMAXUW}
+{0x3F} 66, {InvalidOpCode/VPMAXUD}
+{0x40} 66, {InvalidOpCode/VPMULLD}
+{0x41} 66, {InvalidOpCode/VPHMINPOSUW}
+{0x42} 00, {InvalidOpCode}
+{0x43} 00, {InvalidOpCode}
+{0x44} 00, {InvalidOpCode}
+{0x45} 66, {VPSRLVQ/InvalidOpCode}
+{0x46} 66, {VPSRAVD/InvalidOpCode}
+{0x47} 66, {VPSLLVQ/VPSLLVD/InvalidOpCode}
+{0x48} 00, {InvalidOpCode}
+{0x49} 00, {InvalidOpCode}
+{0x4A} 00, {InvalidOpCode}
+{0x4B} 00, {InvalidOpCode}
+{0x4C} 00, {InvalidOpCode}
+{0x4D} 00, {InvalidOpCode}
+{0x4E} 00, {InvalidOpCode}
+{0x4F} 00, {InvalidOpCode}
+{0x50} 00, {InvalidOpCode}
+{0x51} 00, {InvalidOpCode}
+{0x52} 00, {InvalidOpCode}
+{0x53} 00, {InvalidOpCode}
+{0x54} 00, {InvalidOpCode}
+{0x55} 00, {InvalidOpCode}
+{0x56} 00, {InvalidOpCode}
+{0x57} 00, {InvalidOpCode}
+{0x58} 66, {VPBROADCASTD/InvalidOpCode}
+{0x59} 66, {VPBROADCASTQ/InvalidOpCode}
+{0x5A} 66, {VBROADCASTI128/InvalidOpCode}
+{0x5B} 00, {InvalidOpCode}
+{0x5C} 00, {InvalidOpCode}
+{0x5D} 00, {InvalidOpCode}
+{0x5E} 00, {InvalidOpCode}
+{0x5F} 00, {InvalidOpCode}
+{0x60} 00, {InvalidOpCode}
+{0x61} 00, {InvalidOpCode}
+{0x62} 00, {InvalidOpCode}
+{0x63} 00, {InvalidOpCode}
+{0x64} 00, {InvalidOpCode}
+{0x65} 00, {InvalidOpCode}
+{0x66} 00, {InvalidOpCode}
+{0x67} 00, {InvalidOpCode}
+{0x68} 00, {InvalidOpCode}
+{0x69} 00, {InvalidOpCode}
+{0x6A} 00, {InvalidOpCode}
+{0x6B} 00, {InvalidOpCode}
+{0x6C} 00, {InvalidOpCode}
+{0x6D} 00, {InvalidOpCode}
+{0x6E} 00, {InvalidOpCode}
+{0x6F} 00, {InvalidOpCode}
+{0x70} 00, {InvalidOpCode}
+{0x71} 00, {InvalidOpCode}
+{0x72} 00, {InvalidOpCode}
+{0x73} 00, {InvalidOpCode}
+{0x74} 00, {InvalidOpCode}
+{0x75} 00, {InvalidOpCode}
+{0x76} 00, {InvalidOpCode}
+{0x77} 00, {InvalidOpCode}
+{0x78} 66, {VPBROADCASTB/InvalidOpCode}
+{0x79} 66, {VPBROADCASTW/InvalidOpCode}
+{0x7A} 00, {InvalidOpCode}
+{0x7B} 00, {InvalidOpCode}
+{0x7C} 00, {InvalidOpCode}
+{0x7D} 00, {InvalidOpCode}
+{0x7E} 00, {InvalidOpCode}
+{0x7F} 00, {InvalidOpCode}
+{0x80} 66, {INVPCID}
+{0x81} 66, {INVVPID}
+{0x82} 66, {INVPCID}
+{0x83} 00, {InvalidOpCode}
+{0x84} 00, {InvalidOpCode}
+{0x85} 00, {InvalidOpCode}
+{0x86} 00, {InvalidOpCode}
+{0x87} 00, {InvalidOpCode}
+{0x88} 00, {InvalidOpCode}
+{0x89} 00, {InvalidOpCode}
+{0x8A} 00, {InvalidOpCode}
+{0x8B} 00, {InvalidOpCode}
+{0x8C} 66, {VPMASKMOVD/VPMASKMOVQ/InvalidOpCode}
+{0x8D} 00, {InvalidOpCode}
+{0x8E} 66, {VPMASKMOVD/VPMASKMOVQ/InvalidOpCode}
+{0x8F} 00, {InvalidOpCode}
+{0x90} 66, {VPGATHERDD/VPGATHERDQ}
+{0x91} 66, {VPGATHERQD/VPGATHERQQ}
+{0x92} 66, {VGATHERDPS/VGATHERDPD}
+{0x93} 66, {VGATHERQPS/VGATHERQPD}
+{0x94} 00, {InvalidOpCode}
+{0x95} 00, {InvalidOpCode}
+{0x96} 66, {VFMADDSUB132PS/VFMADDSUB132PD}
+{0x97} 66, {VFMSUBADD132PS/VFMSUBADD132PD}
+{0x98} 66, {VFMADD132PS/VFMADD132PD}
+{0x99} 66, {VFMADD132SS/VFMADD132SD}
+{0x9A} 66, {VFMSUB132PS/VFMSUB132PD}
+{0x9B} 66, {VFMSUB132SS/VFMSUB132SD}
+{0x9C} 66, {VFNMADD132PS/VFNMADD132PD}
+{0x9D} 66, {VFNMADD132SS/VFNMADD132SD}
+{0x9E} 66, {VFNMSUB132PS/VFNMSUB132PD}
+{0x9F} 66, {VFNMSUB132SS/VFNMSUB132SD}
+{0xA0} 00, {InvalidOpCode}
+{0xA1} 00, {InvalidOpCode}
+{0xA2} 00, {InvalidOpCode}
+{0xA3} 00, {InvalidOpCode}
+{0xA4} 00, {InvalidOpCode}
+{0xA5} 00, {InvalidOpCode}
+{0xA6} 66, {VFMADDSUB213PS/VFMADDSUB213PD}
+{0xA7} 66, {VFMSUBADD213PS/VFMSUBADD213PD}
+{0xA8} 66, {VFMADD213PS/VFMADD213PD}
+{0xA9} 66, {VFMADD213SS/VFMADD213SD}
+{0xAA} 66, {VFMSUB213PS/VFMSUB213PD}
+{0xAB} 66, {VFMSUB213SS/VFMSUB213SD}
+{0xAC} 66, {VFNMADD213PS/VFNMADD213PD}
+{0xAD} 66, {VFNMADD213SS/VFNMADD213SD}
+{0xAE} 66, {VFNMSUB213PS/VFNMSUB213PD}
+{0xAF} 66, {VFNMSUB213SS/VFNMSUB213SD}
+{0xB0} 00, {InvalidOpCode}
+{0xB1} 00, {InvalidOpCode}
+{0xB2} 00, {InvalidOpCode}
+{0xB3} 00, {InvalidOpCode}
+{0xB4} 00, {InvalidOpCode}
+{0xB5} 00, {InvalidOpCode}
+{0xB6} 66, {VFMADDSUB231PS/VFMADDSUB231PD}
+{0xB7} 66, {VFMSUBADD231PS/VFMSUBADD231PD}
+{0xB8} 66, {VFMADD231PS/VFMADD231PD}
+{0xB9} 66, {VFMADD231SS/VFMADD231SD}
+{0xBA} 66, {VFMSUB231PS/VFMSUB231PD}
+{0xBB} 66, {VFMSUB231SS/VFMSUB231SD}
+{0xBC} 66, {VFNMADD231PS/VFNMADD231PD}
+{0xBD} 66, {VFNMADD231SS/VFNMADD231SD}
+{0xBE} 66, {VFNMSUB231PS/VFNMSUB231PD}
+{0xBF} 66, {VFNMSUB231SS/VFNMSUB231SD}
+{0xC0} 00, {InvalidOpCode}
+{0xC1} 00, {InvalidOpCode}
+{0xC2} 00, {InvalidOpCode}
+{0xC3} 00, {InvalidOpCode}
+{0xC4} 00, {InvalidOpCode}
+{0xC5} 00, {InvalidOpCode}
+{0xC6} 00, {InvalidOpCode}
+{0xC7} 00, {InvalidOpCode}
+{0xC8} 01, {SHA1NEXTE}
+{0xC9} 01, {SHA1MSG1}
+{0xCA} 01, {SHA1MSG2}
+{0xCB} 01, {SHA256RNDS2}
+{0xCC} 01, {SHA256MSG1}
+{0xCD} 01, {SHA256MSG2}
+{0xCE} 00, {InvalidOpCode}
+{0xCF} 00, {InvalidOpCode}
+{0xD0} 00, {InvalidOpCode}
+{0xD1} 00, {InvalidOpCode}
+{0xD2} 00, {InvalidOpCode}
+{0xD3} 00, {InvalidOpCode}
+{0xD4} 00, {InvalidOpCode}
+{0xD5} 00, {InvalidOpCode}
+{0xD6} 00, {InvalidOpCode}
+{0xD7} 00, {InvalidOpCode}
+{0xD8} 00, {InvalidOpCode}
+{0xD9} 00, {InvalidOpCode}
+{0xDA} 00, {InvalidOpCode}
+{0xDB} 66, {VAESIMC}
+{0xDC} 66, {VAESENC}
+{0xDD} 66, {VAESENCLAST}
+{0xDE} 66, {VAESDEC}
+{0xDF} 66, {VAESDECLAST}
+{0xE0} 00, {InvalidOpCode}
+{0xE1} 00, {InvalidOpCode}
+{0xE2} 00, {InvalidOpCode}
+{0xE3} 00, {InvalidOpCode}
+{0xE4} 00, {InvalidOpCode}
+{0xE5} 00, {InvalidOpCode}
+{0xE6} 00, {InvalidOpCode}
+{0xE7} 00, {InvalidOpCode}
+{0xE8} 00, {InvalidOpCode}
+{0xE9} 00, {InvalidOpCode}
+{0xEA} 00, {InvalidOpCode}
+{0xEB} 00, {InvalidOpCode}
+{0xEC} 00, {InvalidOpCode}
+{0xED} 00, {InvalidOpCode}
+{0xEE} 00, {InvalidOpCode}
+{0xEF} 00, {InvalidOpCode}
+{0xF0} 81, {MOVBE/InvalidOpCode/CRC32}
+{0xF1} 81, {MOVBE/InvalidOpCode/CRC32}
+{0xF2} 81, {ANDNv/InvalidOpCode}
+{0xF3} 81, {group_17}
+{0xF4} 81, {InvalidOpCode}
+{0xF5} 81, {PDEPv/PEXTv/BZHIv/InvalidOpCode}
+{0xF6} 81, {MULXv/ADCX/ADOX/InvalidOpCode}
+{0xF7} 81, {SHLXv/SHRXv/SARXv/BEXTRv/InvalidOpCode}
+{0xF8} 00, {InvalidOpCode}
+{0xF9} 00, {InvalidOpCode}
+{0xFA} 00, {InvalidOpCode}
+{0xFB} 00, {InvalidOpCode}
+{0xFC} 00, {InvalidOpCode}
+{0xFD} 00, {InvalidOpCode}
+{0xFE} 00, {InvalidOpCode}
+{0xFF} 00 {InvalidOpCode}
+);
+{============================================
+ ThreeByteTable3A
+============================================}
+const ThreeByteTable3A : array[Byte] of Byte =(//
+{0x00} 82, {VPERMQ/InvalidOpCode}
+{0x01} 82, {VPERMPD/InvalidOpCode}
+{0x02} 82, {VPBLENDD/InvalidOpCode}
+{0x03} 00, {InvalidOpCode}
+{0x04} 82, {VPERMILPS/InvalidOpCode}
+{0x05} 82, {VPERMILPD/InvalidOpCode}
+{0x06} 82, {VPERM2F128/InvalidOpCode}
+{0x07} 00, {InvalidOpCode}
+{0x08} 82, {InvalidOpCode/VROUNDPS}
+{0x09} 82, {InvalidOpCode/VROUNDPD}
+{0x0A} 82, {InvalidOpCode/VROUNDSS}
+{0x0B} 82, {InvalidOpCode/VROUNDSD}
+{0x0C} 82, {InvalidOpCode/VBLENDPS}
+{0x0D} 82, {InvalidOpCode/VBLENDPD}
+{0x0E} 82, {InvalidOpCode/VPBLENDW}
+{0x0F} 77, {VPALIGNR/PALIGNR}
+{0x10} 00, {InvalidOpCode}
+{0x11} 00, {InvalidOpCode}
+{0x12} 00, {InvalidOpCode}
+{0x13} 00, {InvalidOpCode}
+{0x14} 82, {InvalidOpCode/VPEXTRB}
+{0x15} 82, {InvalidOpCode/VPEXTRW}
+{0x16} 82, {InvalidOpCode/VPEXTRD}
+{0x17} 82, {InvalidOpCode/VEXTRACTPS}
+{0x18} 82, {VINSERTF128/InvalidOpCode}
+{0x19} 82, {VEXTRACTF128/InvalidOpCode}
+{0x1A} 00, {InvalidOpCode}
+{0x1B} 00, {InvalidOpCode}
+{0x1C} 00, {InvalidOpCode}
+{0x1D} 82, {VCVTPS2PH/InvalidOpCode}
+{0x1E} 00, {InvalidOpCode}
+{0x1F} 00, {InvalidOpCode}
+{0x20} 82, {InvalidOpCode/VINSERTPS}
+{0x21} 82, {InvalidOpCode/VPINSRD}
+{0x22} 00, {InvalidOpCode}
+{0x23} 00, {InvalidOpCode}
+{0x24} 00, {InvalidOpCode}
+{0x25} 00, {InvalidOpCode}
+{0x26} 00, {InvalidOpCode}
+{0x27} 00, {InvalidOpCode}
+{0x28} 00, {InvalidOpCode}
+{0x29} 00, {InvalidOpCode}
+{0x2A} 00, {InvalidOpCode}
+{0x2B} 00, {InvalidOpCode}
+{0x2C} 00, {InvalidOpCode}
+{0x2D} 00, {InvalidOpCode}
+{0x2E} 00, {InvalidOpCode}
+{0x2F} 00, {InvalidOpCode}
+{0x30} 00, {InvalidOpCode}
+{0x31} 00, {InvalidOpCode}
+{0x32} 00, {InvalidOpCode}
+{0x33} 00, {InvalidOpCode}
+{0x34} 00, {InvalidOpCode}
+{0x35} 00, {InvalidOpCode}
+{0x36} 00, {InvalidOpCode}
+{0x37} 00, {InvalidOpCode}
+{0x38} 82, {VINSERTI128/InvalidOpCode}
+{0x39} 82, {VEXTRACTI128/InvalidOpCode}
+{0x3A} 00, {InvalidOpCode}
+{0x3B} 00, {InvalidOpCode}
+{0x3C} 00, {InvalidOpCode}
+{0x3D} 00, {InvalidOpCode}
+{0x3E} 00, {InvalidOpCode}
+{0x3F} 00, {InvalidOpCode}
+{0x40} 82, {InvalidOpCode/VDPPS}
+{0x41} 82, {InvalidOpCode/VDPPD}
+{0x42} 82, {InvalidOpCode/VMPSADBW}
+{0x43} 00, {InvalidOpCode}
+{0x44} 82, {InvalidOpCode/VPCLMULQDQ}
+{0x45} 00, {InvalidOpCode}
+{0x46} 82, {VPERM2I128/InvalidOpCode}
+{0x47} 00, {InvalidOpCode}
+{0x48} 82, {VPERMILzz2PS/InvalidOpCode}
+{0x49} 82, {VPERMILzz2PD/InvalidOpCode}
+{0x4A} 66, {VBLENDVPS/InvalidOpCode}
+{0x4B} 66, {VBLENDVPD/InvalidOpCode}
+{0x4C} 66, {VPBLENDVB/InvalidOpCode}
+{0x4D} 00, {InvalidOpCode}
+{0x4E} 00, {InvalidOpCode}
+{0x4F} 00, {InvalidOpCode}
+{0x50} 00, {InvalidOpCode}
+{0x51} 00, {InvalidOpCode}
+{0x52} 00, {InvalidOpCode}
+{0x53} 00, {InvalidOpCode}
+{0x54} 00, {InvalidOpCode}
+{0x55} 00, {InvalidOpCode}
+{0x56} 00, {InvalidOpCode}
+{0x57} 00, {InvalidOpCode}
+{0x58} 00, {InvalidOpCode}
+{0x59} 00, {InvalidOpCode}
+{0x5A} 00, {InvalidOpCode}
+{0x5B} 00, {InvalidOpCode}
+{0x5C} 66, {VFMADDSUBPS/InvalidOpCode}
+{0x5D} 66, {VFMADDSUBPD/InvalidOpCode}
+{0x5E} 66, {VFMSUBADDPS/InvalidOpCode}
+{0x5F} 66, {VFMSUBADDPD/InvalidOpCode}
+{0x60} 82, {InvalidOpCode/VPCMPESTRM}
+{0x61} 82, {InvalidOpCode/VPCMPESTRI}
+{0x62} 82, {InvalidOpCode/VPCMPISTRM}
+{0x63} 82, {InvalidOpCode/VPCMPISTRI}
+{0x64} 00, {InvalidOpCode}
+{0x65} 00, {InvalidOpCode}
+{0x66} 00, {InvalidOpCode}
+{0x67} 00, {InvalidOpCode}
+{0x68} 66, {VFMADDPS/InvalidOpCode}
+{0x69} 66, {VFMADDPD/InvalidOpCode}
+{0x6A} 66, {VFMADDSS/InvalidOpCode}
+{0x6B} 66, {VFMADDSD/InvalidOpCode}
+{0x6C} 66, {VFMSUBPS/InvalidOpCode}
+{0x6D} 66, {VFMSUBPD/InvalidOpCode}
+{0x6E} 66, {VFMSUBSS/InvalidOpCode}
+{0x6F} 66, {VFMSUBSD/InvalidOpCode}
+{0x70} 00, {InvalidOpCode}
+{0x71} 00, {InvalidOpCode}
+{0x72} 00, {InvalidOpCode}
+{0x73} 00, {InvalidOpCode}
+{0x74} 00, {InvalidOpCode}
+{0x75} 00, {InvalidOpCode}
+{0x76} 00, {InvalidOpCode}
+{0x77} 00, {InvalidOpCode}
+{0x78} 66, {VFNMADDPS/InvalidOpCode}
+{0x79} 66, {VFNMADDPD/InvalidOpCode}
+{0x7A} 66, {VFNMADDSS/InvalidOpCode}
+{0x7B} 66, {VFNMADDSD/InvalidOpCode}
+{0x7C} 66, {VFNMSUBPS/InvalidOpCode}
+{0x7D} 66, {VFNMSUBPD/InvalidOpCode}
+{0x7E} 66, {VFNMSUBSS/InvalidOpCode}
+{0x7F} 66, {VFNMSUBSD/InvalidOpCode}
+{0x80} 00, {InvalidOpCode}
+{0x81} 00, {InvalidOpCode}
+{0x82} 00, {InvalidOpCode}
+{0x83} 00, {InvalidOpCode}
+{0x84} 00, {InvalidOpCode}
+{0x85} 00, {InvalidOpCode}
+{0x86} 00, {InvalidOpCode}
+{0x87} 00, {InvalidOpCode}
+{0x88} 00, {InvalidOpCode}
+{0x89} 00, {InvalidOpCode}
+{0x8A} 00, {InvalidOpCode}
+{0x8B} 00, {InvalidOpCode}
+{0x8C} 00, {InvalidOpCode}
+{0x8D} 00, {InvalidOpCode}
+{0x8E} 00, {InvalidOpCode}
+{0x8F} 00, {InvalidOpCode}
+{0x90} 00, {InvalidOpCode}
+{0x91} 00, {InvalidOpCode}
+{0x92} 00, {InvalidOpCode}
+{0x93} 00, {InvalidOpCode}
+{0x94} 00, {InvalidOpCode}
+{0x95} 00, {InvalidOpCode}
+{0x96} 00, {InvalidOpCode}
+{0x97} 00, {InvalidOpCode}
+{0x98} 00, {InvalidOpCode}
+{0x99} 00, {InvalidOpCode}
+{0x9A} 00, {InvalidOpCode}
+{0x9B} 00, {InvalidOpCode}
+{0x9C} 00, {InvalidOpCode}
+{0x9D} 00, {InvalidOpCode}
+{0x9E} 00, {InvalidOpCode}
+{0x9F} 00, {InvalidOpCode}
+{0xA0} 00, {InvalidOpCode}
+{0xA1} 00, {InvalidOpCode}
+{0xA2} 00, {InvalidOpCode}
+{0xA3} 00, {InvalidOpCode}
+{0xA4} 00, {InvalidOpCode}
+{0xA5} 00, {InvalidOpCode}
+{0xA6} 00, {InvalidOpCode}
+{0xA7} 00, {InvalidOpCode}
+{0xA8} 00, {InvalidOpCode}
+{0xA9} 00, {InvalidOpCode}
+{0xAA} 00, {InvalidOpCode}
+{0xAB} 00, {InvalidOpCode}
+{0xAC} 00, {InvalidOpCode}
+{0xAD} 00, {InvalidOpCode}
+{0xAE} 00, {InvalidOpCode}
+{0xAF} 00, {InvalidOpCode}
+{0xB0} 00, {InvalidOpCode}
+{0xB1} 00, {InvalidOpCode}
+{0xB2} 00, {InvalidOpCode}
+{0xB3} 00, {InvalidOpCode}
+{0xB4} 00, {InvalidOpCode}
+{0xB5} 00, {InvalidOpCode}
+{0xB6} 00, {InvalidOpCode}
+{0xB7} 00, {InvalidOpCode}
+{0xB8} 00, {InvalidOpCode}
+{0xB9} 00, {InvalidOpCode}
+{0xBA} 00, {InvalidOpCode}
+{0xBB} 00, {InvalidOpCode}
+{0xBC} 00, {InvalidOpCode}
+{0xBD} 00, {InvalidOpCode}
+{0xBE} 00, {InvalidOpCode}
+{0xBF} 00, {InvalidOpCode}
+{0xC0} 00, {InvalidOpCode}
+{0xC1} 00, {InvalidOpCode}
+{0xC2} 00, {InvalidOpCode}
+{0xC3} 00, {InvalidOpCode}
+{0xC4} 00, {InvalidOpCode}
+{0xC5} 00, {InvalidOpCode}
+{0xC6} 00, {InvalidOpCode}
+{0xC7} 00, {InvalidOpCode}
+{0xC8} 00, {InvalidOpCode}
+{0xC9} 00, {InvalidOpCode}
+{0xCA} 00, {InvalidOpCode}
+{0xCB} 00, {InvalidOpCode}
+{0xCC} 20, {SHA1RNDS4}
+{0xCD} 00, {InvalidOpCode}
+{0xCE} 00, {InvalidOpCode}
+{0xCF} 00, {InvalidOpCode}
+{0xD0} 00, {InvalidOpCode}
+{0xD1} 00, {InvalidOpCode}
+{0xD2} 00, {InvalidOpCode}
+{0xD3} 00, {InvalidOpCode}
+{0xD4} 00, {InvalidOpCode}
+{0xD5} 00, {InvalidOpCode}
+{0xD6} 00, {InvalidOpCode}
+{0xD7} 00, {InvalidOpCode}
+{0xD8} 00, {InvalidOpCode}
+{0xD9} 00, {InvalidOpCode}
+{0xDA} 00, {InvalidOpCode}
+{0xDB} 00, {InvalidOpCode}
+{0xDC} 00, {InvalidOpCode}
+{0xDD} 00, {InvalidOpCode}
+{0xDE} 00, {InvalidOpCode}
+{0xDF} 82, {VAESKEYGENASSIST}
+{0xE0} 00, {InvalidOpCode}
+{0xE1} 00, {InvalidOpCode}
+{0xE2} 00, {InvalidOpCode}
+{0xE3} 00, {InvalidOpCode}
+{0xE4} 00, {InvalidOpCode}
+{0xE5} 00, {InvalidOpCode}
+{0xE6} 00, {InvalidOpCode}
+{0xE7} 00, {InvalidOpCode}
+{0xE8} 00, {InvalidOpCode}
+{0xE9} 00, {InvalidOpCode}
+{0xEA} 00, {InvalidOpCode}
+{0xEB} 00, {InvalidOpCode}
+{0xEC} 00, {InvalidOpCode}
+{0xED} 00, {InvalidOpCode}
+{0xEE} 00, {InvalidOpCode}
+{0xEF} 00, {InvalidOpCode}
+{0xF0} 83, {RORXv}
+{0xF1} 00, {InvalidOpCode}
+{0xF2} 00, {InvalidOpCode}
+{0xF3} 00, {InvalidOpCode}
+{0xF4} 00, {InvalidOpCode}
+{0xF5} 00, {InvalidOpCode}
+{0xF6} 00, {InvalidOpCode}
+{0xF7} 00, {InvalidOpCode}
+{0xF8} 00, {InvalidOpCode}
+{0xF9} 00, {InvalidOpCode}
+{0xFA} 00, {InvalidOpCode}
+{0xFB} 00, {InvalidOpCode}
+{0xFC} 00, {InvalidOpCode}
+{0xFD} 00, {InvalidOpCode}
+{0xFE} 00, {InvalidOpCode}
+{0xFF} 00 {InvalidOpCode}
+);
diff --git a/components/detours/packages/DelphiXE5/detours.dpk b/components/detours/packages/DelphiXE5/detours.dpk
new file mode 100644
index 00000000..1b2deb9c
--- /dev/null
+++ b/components/detours/packages/DelphiXE5/detours.dpk
@@ -0,0 +1,38 @@
+package detours;
+
+{$R *.res}
+{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
+{$ALIGN 8}
+{$ASSERTIONS ON}
+{$BOOLEVAL OFF}
+{$DEBUGINFO ON}
+{$EXTENDEDSYNTAX ON}
+{$IMPORTEDDATA ON}
+{$IOCHECKS ON}
+{$LOCALSYMBOLS ON}
+{$LONGSTRINGS ON}
+{$OPENSTRINGS ON}
+{$OPTIMIZATION OFF}
+{$OVERFLOWCHECKS OFF}
+{$RANGECHECKS OFF}
+{$REFERENCEINFO ON}
+{$SAFEDIVIDE OFF}
+{$STACKFRAMES ON}
+{$TYPEDADDRESS OFF}
+{$VARSTRINGCHECKS ON}
+{$WRITEABLECONST OFF}
+{$MINENUMSIZE 1}
+{$IMAGEBASE $400000}
+{$DEFINE DEBUG}
+{$ENDIF IMPLICITBUILDING}
+{$IMPLICITBUILD ON}
+
+requires
+ rtl;
+
+contains
+ CPUID in '..\..\Source\CPUID.pas',
+ DDetours in '..\..\Source\DDetours.pas',
+ InstDecode in '..\..\Source\InstDecode.pas';
+
+end.
diff --git a/components/detours/packages/DelphiXE5/detours.dproj b/components/detours/packages/DelphiXE5/detours.dproj
new file mode 100644
index 00000000..cc0dee1a
--- /dev/null
+++ b/components/detours/packages/DelphiXE5/detours.dproj
@@ -0,0 +1,173 @@
+
+
+ {0B99D52D-E87E-4E6E-A53E-DD727D4A0EBA}
+ detours.dpk
+ 15.3
+ None
+ True
+ Release
+ Win64
+ 3
+ Package
+
+
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Base
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Base
+ true
+
+
+ 1031
+ All
+ System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)
+ true
+ true
+ ..\..\build\$(Platform)
+ .\$(Platform)\$(Config)
+
+
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
+ true
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
+ 1033
+
+
+ Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
+ true
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
+ 1033
+
+
+ DEBUG;$(DCC_Define)
+ true
+ false
+ true
+ true
+ true
+
+
+ false
+
+
+ false
+ RELEASE;$(DCC_Define)
+ 0
+ 0
+
+
+
+ MainSource
+
+
+
+
+
+
+ Cfg_2
+ Base
+
+
+ Base
+
+
+ Cfg_1
+ Base
+
+
+
+ Delphi.Personality.12
+ Package
+
+
+
+ True
+ False
+ 1
+ 0
+ 0
+ 0
+ False
+ False
+ False
+ False
+ False
+ 1031
+ 1252
+
+
+
+
+ 1.0.0.0
+
+
+
+
+
+ 1.0.0.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Microsoft Office 2000 Beispiele für gekapselte Komponenten für Automatisierungsserver
+ Microsoft Office XP Beispiele für gekapselte Komponenten für Automation Server
+
+
+ detours.dpk
+
+
+
+
+ True
+ True
+
+
+ 12
+
+
+
+
diff --git a/components/detours/packages/DelphiXE5/detours.dproj.local b/components/detours/packages/DelphiXE5/detours.dproj.local
new file mode 100644
index 00000000..d576f039
--- /dev/null
+++ b/components/detours/packages/DelphiXE5/detours.dproj.local
@@ -0,0 +1,2 @@
+
+
diff --git a/components/detours/packages/DelphiXE5/detours.res b/components/detours/packages/DelphiXE5/detours.res
new file mode 100644
index 00000000..27efe49b
Binary files /dev/null and b/components/detours/packages/DelphiXE5/detours.res differ
diff --git a/packages/delphiXE5/heidisql.dpr b/packages/delphiXE5/heidisql.dpr
index 501997dd..82a751d0 100644
--- a/packages/delphiXE5/heidisql.dpr
+++ b/packages/delphiXE5/heidisql.dpr
@@ -42,7 +42,8 @@ uses
gnugettext in '..\..\source\gnugettext.pas',
JumpList in '..\..\source\JumpList.pas',
extra_controls in '..\..\source\extra_controls.pas',
- change_password in '..\..\source\change_password.pas' {frmPasswordChange};
+ change_password in '..\..\source\change_password.pas' {frmPasswordChange},
+ Vcl.FormsFix in '..\..\source\Vcl.FormsFix.pas';
{$R ..\..\res\icon.RES}
{$R ..\..\res\icon-question.RES}
diff --git a/packages/delphiXE5/heidisql.dproj b/packages/delphiXE5/heidisql.dproj
index f19373d0..0268a547 100644
--- a/packages/delphiXE5/heidisql.dproj
+++ b/packages/delphiXE5/heidisql.dproj
@@ -7,8 +7,8 @@
3
Application
VCL
- 15.1
- Win32
+ 15.3
+ Win64
true
@@ -28,6 +28,18 @@
Base
true
+
+ true
+ Cfg_1
+ true
+ true
+
+
+ true
+ Cfg_1
+ true
+ true
+
true
Base
@@ -39,12 +51,18 @@
true
true
+
+ true
+ Cfg_2
+ true
+ true
+
false
false
..\..\out\
..\..\build\$(Platform)
- ..\..\components\synedit\build\$(Platform);..\..\components\virtualtreeview\build\$(Platform);..\..\components\synedit\source;..\..\components\virtualtreeview\source;$(DCC_UnitSearchPath)
+ ..\..\components\synedit\build\$(Platform);..\..\components\virtualtreeview\build\$(Platform);..\..\components\synedit\source;..\..\components\virtualtreeview\source;..\..\components\detours\Source;..\..\components\detours\build\$(Platform);$(DCC_UnitSearchPath)
$(BDS)\bin\default_app.manifest
false
false
@@ -59,14 +77,11 @@
Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
- $(BDS)\bin\default_app.manifest
true
CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
- 1033
Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)
- $(BDS)\bin\default_app.manifest
CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
true
@@ -76,13 +91,21 @@
0
0
+
+ true
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
+
+
+ true
+ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
+
- $(BDS)\bin\default_app.manifest
true
DEBUG;$(DCC_Define)
false
+ None
2
3
madExcept;$(DCC_Define)
@@ -90,6 +113,8 @@
CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=
+ true
+ None
2
madExcept;$(DCC_Define)
true
@@ -198,6 +223,7 @@
dfm
+
Cfg_2
Base
@@ -269,14 +295,15 @@
- Microsoft Office 2000 Sample Automation Server Wrapper Components
- Microsoft Office XP Sample Automation Server Wrapper Components
+ Microsoft Office 2000 Beispiele für gekapselte Komponenten für Automatisierungsserver
+ Microsoft Office XP Beispiele für gekapselte Komponenten für Automation Server
True
True
+ False
12
diff --git a/packages/delphiXE5/heidisql.groupproj b/packages/delphiXE5/heidisql.groupproj
index 0f5608e4..00d5f6e0 100644
--- a/packages/delphiXE5/heidisql.groupproj
+++ b/packages/delphiXE5/heidisql.groupproj
@@ -15,6 +15,9 @@
+
+
+
@@ -62,6 +65,15 @@
+
+
+
+
+
+
+
+
+
@@ -72,13 +84,13 @@
-
+
-
+
-
+
diff --git a/source/Vcl.FormsFix.pas b/source/Vcl.FormsFix.pas
new file mode 100644
index 00000000..a2c012f9
--- /dev/null
+++ b/source/Vcl.FormsFix.pas
@@ -0,0 +1,123 @@
+unit Vcl.FormsFix;
+
+interface
+
+implementation
+
+uses
+ System.SysUtils, Winapi.Windows, Vcl.Forms, Vcl.Graphics, System.UITypes
+ //
+ , DDetours
+ //
+ ;
+
+var
+ trampoline_GetMetricSettings: Procedure = nil;
+
+type
+ TFontHelper = class helper for TFont
+ public
+ function Equals(const AOther: TFont): Boolean;
+ end;
+
+function TFontHelper.Equals(const AOther: TFont): Boolean;
+begin
+ Result := (AOther.PixelsPerInch = self.PixelsPerInch)
+ and (AOther.Charset = self.Charset)
+ and (AOther.Color = self.Color)
+ and (AOther.Height = self.Height)
+ and (AOther.Name = self.Name)
+ and (AOther.Orientation = self.Orientation)
+ and (AOther.Pitch = self.Pitch)
+ and (AOther.Size = self.Size)
+ and (AOther.Style = self.Style)
+ and (AOther.Quality = self.Quality);
+end;
+
+type
+ TScreenHelper = class Helper for TScreen
+ public
+ function getPtr_GetMetricSettings:Pointer;
+ end;
+
+function TScreenHelper.getPtr_GetMetricSettings:Pointer;
+begin
+ result:=@TScreen.GetMetricSettings;
+end;
+
+procedure HookedGetMetricSettings(const Self);
+
+ procedure CheckedFontChange(const ACurrFont: TFont; const ANewFont: tagLOGFONTW);
+ var
+ TmpFont: TFont;
+ begin
+ TmpFont := TFont.Create;
+ try
+ TmpFont.Assign(ACurrFont);
+ TmpFont.Handle := CreateFontIndirect(ANewFont);
+ if not TmpFont.Equals(ACurrFont) then
+ begin
+ ACurrFont.Handle := CreateFontIndirect(ANewFont);
+ end;
+ finally
+ FreeAndNil(TmpFont);
+ end;
+ end;
+
+var
+ LSize: Cardinal;
+ LogFont: TLogFont;
+ NonClientMetrics: TNonClientMetrics;
+ SaveShowHint: Boolean;
+
+begin
+ SaveShowHint := False;
+ if Assigned(Application) then SaveShowHint := Application.ShowHint;
+ try
+ if Assigned(Application) then Application.ShowHint := False;
+{$IF DEFINED(CLR)}
+ LSize := Marshal.SizeOf(TypeOf(TLogFont));
+{$ELSE}
+ LSize := SizeOf(TLogFont);
+{$IFEND}
+ if SystemParametersInfo(SPI_GETICONTITLELOGFONT, LSize, {$IFNDEF CLR}@{$ENDIF}LogFont, 0) then
+ begin
+ CheckedFontChange(Screen.IconFont, LogFont);
+ end
+ else
+ Screen.IconFont.Handle := GetStockObject(SYSTEM_FONT);
+{$IF DEFINED(CLR)}
+ LSize := Marshal.SizeOf(TypeOf(TNonClientMetrics));
+{$ELSE}
+ LSize := TNonClientMetrics.SizeOf;
+{$IFEND}
+ NonClientMetrics.cbSize := LSize;
+ if SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, {$IFNDEF CLR}@{$ENDIF}NonClientMetrics, 0) then
+ begin
+ CheckedFontChange(Screen.HintFont, NonClientMetrics.lfStatusFont);
+ CheckedFontChange(Screen.MenuFont, NonClientMetrics.lfMenuFont);
+ CheckedFontChange(Screen.MessageFont, NonClientMetrics.lfMessageFont);
+ CheckedFontChange(Screen.CaptionFont, NonClientMetrics.lfCaptionFont);
+ end else
+ begin
+ Screen.HintFont.Size := 8;
+ Screen.MenuFont.Handle := GetStockObject(SYSTEM_FONT);
+ Screen.MessageFont.Handle := GetStockObject(SYSTEM_FONT);
+ Screen.CaptionFont.Handle := GetStockObject(SYSTEM_FONT);
+ end;
+ Screen.HintFont.Color := clInfoText;
+ Screen.MenuFont.Color := clMenuText;
+ Screen.MessageFont.Color := clWindowText;
+ finally
+ if Assigned(Application) then Application.ShowHint := SaveShowHint;
+ end;
+
+end;
+
+initialization
+ @trampoline_GetMetricSettings := InterceptCreate(Screen.getPtr_GetMetricSettings, @HookedGetMetricSettings);
+
+finalization
+ InterceptRemove(@trampoline_GetMetricSettings);
+
+end.
diff --git a/source/main.pas b/source/main.pas
index 983ef235..907ecce7 100644
--- a/source/main.pas
+++ b/source/main.pas
@@ -17,7 +17,7 @@ uses
routine_editor, trigger_editor, event_editor, options, EditVar, helpers, createdatabase, table_editor,
TableTools, View, Usermanager, SelectDBObject, connections, sqlhelp, dbconnection,
insertfiles, searchreplace, loaddata, copytable, VTHeaderPopup, Cromis.DirectoryWatch, SyncDB, gnugettext,
- JumpList, System.Actions, System.UITypes, pngimage;
+ JumpList, System.Actions, System.UITypes, pngimage, Vcl.FormsFix;
type