[
  {
    "path": ".gitignore",
    "content": "# Uncomment these types if you want even more clean repository. But be careful.\n# It can make harm to an existing project source. Read explanations below.\n#\n# Resource files are binaries containing manifest, project icon and version info.\n# They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files.\n*.res\n#\n# Type library file (binary). In old Delphi versions it should be stored.\n# Since Delphi 2009 it is produced from .ridl file and can safely be ignored.\n#*.tlb\n#\n# Diagram Portfolio file. Used by the diagram editor up to Delphi 7.\n# Uncomment this if you are not using diagrams or use newer Delphi version.\n#*.ddp\n#\n# Visual LiveBindings file. Added in Delphi XE2.\n# Uncomment this if you are not using LiveBindings Designer.\n#*.vlb\n#\n# Deployment Manager configuration file for your project. Added in Delphi XE2.\n# Uncomment this if it is not mobile development and you do not use remote debug feature.\n#*.deployproj\n#\n\n# Delphi compiler-generated binaries (safe to delete)\n#*.exe\n*.dll\n*.bpl\n*.bpi\n*.dcp\n*.so\n*.apk\n*.drc\n*.map\n*.dres\n*.rsm\n*.tds\n*.dcu\n*.lib\n\n# Delphi autogenerated files (duplicated info)\n*.cfg\n*Resource.rc\n\n# Delphi local files (user-specific info)\n*.local\n*.identcache\n*.projdata\n*.tvsconfig\n*.dsk\n\n# Delphi history and backups\n__history/\n*.~*\n\n# Castalia statistics file\n*.stat\n"
  },
  {
    "path": "CHANGELOG",
    "content": "version 2.2(Jun 9, 2020):\n  +Added support for older Delphi version: Now the minimal supported Delphi version is D7.\n  +Added support for FPC.\n  +Added recursive section feature: EnterRecursiveSection/ExitRecursiveSection.\n  +Added param/tag feature for all InterceptCreate functions.\n  +Added GetTrampolineParam function to get user param.\n  +Added GetCreatorThreadIdFromTrampoline function to get thread id that created the hook/trampoline.\n  +Added detection for non valid trampoline pointer.\n  +Added unittest.\n  +Replaced BeginHooks/BeginUnHooks by BeginTransaction.\n  +Replaced EndHooks/EndUnHooks by EndTransaction.\n  +Replaced GetNHook by GetHookCount.\n  +Replaced TDetours<T> by TIntercept<T,U>/TIntercept<T>\n  +Fixed many bugs related to MultiBytesNop.\n  +Fixed wrong displacement value for some branch instructions on x64.\n  +Fixed wrong offset size on x86 for GetJmpType function.\n  +Removed v1 compatibility.\n  +Now the library does not rely on Object.\n  +Code refactoring.\n\nJan 24,2015:\n  +Added support for vtable patching.\n  +Added GetNHook/IsHooked support for Interface.\n\nJan 20,2015:\n  +Added support to hook Delphi Interface by name.\n\nVersion2 , Mahdi Safsafi:\n  +Many bug fix.\n  +Added new hooking model architecture.\n  +Added multi hook support.\n  +Added COM hook support.\n  +Added instruction maping feature.\n  +Added hook detecting feature.\n  +Added BeginHooks/EndHooks.\n  +Added BeginUnHooks/EndUnHooks.\n  +Added IDetours interface.\n  +Added MultiNop instructions support.\n  +Generate better opcodes.\n  +Improved support for x64.\n  +Improved AllocMemAt function.\n"
  },
  {
    "path": "Clean.bat",
    "content": "rem *****************************************\nrem *        Delphi CleanUp Batch.          *\nrem *                                       *\nrem * Clean identcache,local,dcu,exe,       *\nrem * map,drc files.                        *\nrem * Clean hidden __history folder.        *\nrem *                                       *\nrem *        Author: Mahdi Safsafi          *\nrem *****************************************\n\n@echo off\nSetlocal EnableDelayedExpansion\n\nDel \"*.identcache\" /s/q\nDel \"*.local\" /s/q\nDel \"*.dcu\" /s/q\nDel \"*.exe\" /s/q\nDel \"*.drc\" /s/q\nDel \"*.map\" /s/q\n\nset mustdel=false\nFor /r %%f in (.) do (\n    set \"mustdel=false\"\n\tif %%~nf==Win32 (\n\t\tif exist \"%%~ff\\Debug\\\" set \"mustdel=true\"\n\t\tif exist \"%%~ff\\Release\\\" set \"mustdel=true\"\n) else if %%~nf==Win64 (\n\t\tif exist \"%%~ff\\Debug\\\" set \"mustdel=true\"\n\t\tif exist \"%%~ff\\Release\\\" set \"mustdel=true\" \n\t\t)\nif %%~nf==__history set \"mustdel=true\"\nif !mustdel!==true (\n\tif exist \"%%~ff\" rd /s/q \"%%~ff\"\n        )\n)"
  },
  {
    "path": "Demo/Delphi/D7/D7.dpr",
    "content": "program D7;\n\nuses\n  Forms,\n  uMain in 'uMain.pas' {Main};\n\n{$R *.res}\n\nbegin\n  Application.Initialize;\n  Application.CreateForm(TMain, Main);\n  Application.Run;\nend.\n"
  },
  {
    "path": "Demo/Delphi/D7/uMain.dfm",
    "content": "object Main: TMain\n  Left = 192\n  Top = 125\n  Width = 238\n  Height = 191\n  BorderStyle = bsSizeToolWin\n  Caption = 'Main'\n  Color = clBtnFace\n  Font.Charset = DEFAULT_CHARSET\n  Font.Color = clWindowText\n  Font.Height = -11\n  Font.Name = 'Tahoma'\n  Font.Style = []\n  OldCreateOrder = False\n  OnCreate = FormCreate\n  PixelsPerInch = 96\n  TextHeight = 13\n  object BtnHook: TButton\n    Left = 46\n    Top = 24\n    Width = 131\n    Height = 25\n    Caption = 'Hook'\n    TabOrder = 0\n    OnClick = BtnHookClick\n  end\n  object BtnMsgBox: TButton\n    Left = 46\n    Top = 64\n    Width = 131\n    Height = 25\n    Caption = 'MsgBox'\n    TabOrder = 1\n    OnClick = BtnMsgBoxClick\n  end\n  object BtnUnhook: TButton\n    Left = 46\n    Top = 104\n    Width = 131\n    Height = 25\n    Caption = 'Unhook'\n    TabOrder = 2\n    OnClick = BtnUnhookClick\n  end\nend\n"
  },
  {
    "path": "Demo/Delphi/D7/uMain.pas",
    "content": "unit uMain;\n\ninterface\n\nuses\n  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,\n  Dialogs, StdCtrls, DDetours;\n\ntype\n  TMain = class(TForm)\n    BtnHook: TButton;\n    BtnMsgBox: TButton;\n    BtnUnhook: TButton;\n    procedure BtnHookClick(Sender: TObject);\n    procedure BtnMsgBoxClick(Sender: TObject);\n    procedure BtnUnhookClick(Sender: TObject);\n    procedure FormCreate(Sender: TObject);\n  private\n    { Private declarations }\n  public\n    { Public declarations }\n  end;\n\nvar\n  Main: TMain;\n\nimplementation\n\n{$R *.dfm}\n\ntype TMessageBox = function (hWnd: HWND; lpText, lpCaption: PChar; uType: UINT): Integer; stdcall;\nvar  TrampolineMessageBox : TMessageBox;\n\nfunction InterceptMessageBox(hWnd: HWND; lpText, lpCaption: PChar; uType: UINT): Integer; stdcall;\nvar\n  Self: TMain;\nbegin\n  Self := GetTrampolineParam(TrampolineMessageBox);\n  Self.Caption := 'MessageBox hooked !';\n  Result := TrampolineMessageBox(hWnd, 'this text was hooked', 'this title was hooked', MB_ICONWARNING);\nend;\n\n\nprocedure TMain.FormCreate(Sender: TObject);\nbegin\n  BtnUnHook.Enabled := False;\nend;\n\nprocedure TMain.BtnHookClick(Sender: TObject);\nbegin\n  TrampolineMessageBox := InterceptCreate(@MessageBox, @InterceptMessageBox, Self);\n  BtnUnHook.Enabled := True;\n  BtnHook.Enabled := False;\nend;\n\nprocedure TMain.BtnMsgBoxClick(Sender: TObject);\nbegin\n  MessageBox(0, 'text', 'caption', 0);\nend;\n\nprocedure TMain.BtnUnHookClick(Sender: TObject);\nbegin\n  if Assigned(TrampolineMessageBox) then\n  begin\n    InterceptRemove(@TrampolineMessageBox);\n    TrampolineMessageBox := nil;\n    BtnHook.Enabled := True;\n    BtnUnHook.Enabled := False;\n  end;\nend;\n\ninitialization\n\nfinalization\n\nif Assigned(TrampolineMessageBox) then\n  InterceptRemove(@TrampolineMessageBox);\n\nend.\n\n"
  },
  {
    "path": "Demo/Delphi/Demo1/Demo1.dpr",
    "content": "program Demo1;\n\nuses\n  Vcl.Forms,\n  uMain in 'uMain.pas' {Main},\n  CPUID in '..\\..\\..\\Source\\CPUID.pas',\n  DDetours in '..\\..\\..\\Source\\DDetours.pas',\n  InstDecode in '..\\..\\..\\Source\\InstDecode.pas',\n  LegacyTypes in '..\\..\\..\\Source\\LegacyTypes.pas';\n\n{$R *.res}\n\nbegin\n  Application.Initialize;\n  Application.MainFormOnTaskbar := True;\n  Application.CreateForm(TMain, Main);\n  Application.Run;\nend.\n"
  },
  {
    "path": "Demo/Delphi/Demo1/Demo1.dproj",
    "content": "﻿<Project xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n    <PropertyGroup>\n        <ProjectGuid>{F3F06688-F7C7-4A42-B09B-18B38AB06934}</ProjectGuid>\n        <ProjectVersion>18.7</ProjectVersion>\n        <FrameworkType>VCL</FrameworkType>\n        <MainSource>Demo1.dpr</MainSource>\n        <Base>True</Base>\n        <Config Condition=\"'$(Config)'==''\">Debug</Config>\n        <Platform Condition=\"'$(Platform)'==''\">Win32</Platform>\n        <TargetedPlatforms>1</TargetedPlatforms>\n        <AppType>Application</AppType>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"'$(Config)'=='Base' or '$(Base)'!=''\">\n        <Base>true</Base>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''\">\n        <Base_Win32>true</Base_Win32>\n        <CfgParent>Base</CfgParent>\n        <Base>true</Base>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"('$(Platform)'=='Win64' and '$(Base)'=='true') or '$(Base_Win64)'!=''\">\n        <Base_Win64>true</Base_Win64>\n        <CfgParent>Base</CfgParent>\n        <Base>true</Base>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"'$(Config)'=='Debug' or '$(Cfg_1)'!=''\">\n        <Cfg_1>true</Cfg_1>\n        <CfgParent>Base</CfgParent>\n        <Base>true</Base>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"('$(Platform)'=='Win32' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win32)'!=''\">\n        <Cfg_1_Win32>true</Cfg_1_Win32>\n        <CfgParent>Cfg_1</CfgParent>\n        <Cfg_1>true</Cfg_1>\n        <Base>true</Base>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"'$(Config)'=='Release' or '$(Cfg_2)'!=''\">\n        <Cfg_2>true</Cfg_2>\n        <CfgParent>Base</CfgParent>\n        <Base>true</Base>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"('$(Platform)'=='Win32' and '$(Cfg_2)'=='true') or '$(Cfg_2_Win32)'!=''\">\n        <Cfg_2_Win32>true</Cfg_2_Win32>\n        <CfgParent>Cfg_2</CfgParent>\n        <Cfg_2>true</Cfg_2>\n        <Base>true</Base>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"'$(Base)'!=''\">\n        <DCC_DcuOutput>.\\$(Platform)\\$(Config)</DCC_DcuOutput>\n        <DCC_ExeOutput>.\\$(Platform)\\$(Config)</DCC_ExeOutput>\n        <DCC_E>false</DCC_E>\n        <DCC_N>false</DCC_N>\n        <DCC_S>false</DCC_S>\n        <DCC_F>false</DCC_F>\n        <DCC_K>false</DCC_K>\n        <DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace)</DCC_Namespace>\n        <Icon_MainIcon>$(BDS)\\bin\\delphi_PROJECTICON.ico</Icon_MainIcon>\n        <UWP_DelphiLogo44>$(BDS)\\bin\\Artwork\\Windows\\UWP\\delphi_UwpDefault_44.png</UWP_DelphiLogo44>\n        <UWP_DelphiLogo150>$(BDS)\\bin\\Artwork\\Windows\\UWP\\delphi_UwpDefault_150.png</UWP_DelphiLogo150>\n        <SanitizedProjectName>Demo1</SanitizedProjectName>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"'$(Base_Win32)'!=''\">\n        <DCC_UsePackage>DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;StyleControls_dxe103Rio;vclFireDAC;IndySystem;tethering;svnui;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;svn;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;FMXTee;MyIdePlugin;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;dclAbsDBd26;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;bindcomp;appanalytics;dsnap;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;vclAbsDBd26;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)</DCC_UsePackage>\n        <DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>\n        <BT_BuildType>Debug</BT_BuildType>\n        <VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>\n        <VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>\n        <VerInfo_Locale>1033</VerInfo_Locale>\n        <Manifest_File>$(BDS)\\bin\\default_app.manifest</Manifest_File>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"'$(Base_Win64)'!=''\">\n        <DCC_UsePackage>DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;StyleControls_dxe103Rio;vclFireDAC;IndySystem;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;bindcomp;appanalytics;dsnap;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)</DCC_UsePackage>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"'$(Cfg_1)'!=''\">\n        <DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>\n        <DCC_DebugDCUs>true</DCC_DebugDCUs>\n        <DCC_Optimize>false</DCC_Optimize>\n        <DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>\n        <DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>\n        <DCC_RemoteDebug>true</DCC_RemoteDebug>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"'$(Cfg_1_Win32)'!=''\">\n        <DCC_RemoteDebug>false</DCC_RemoteDebug>\n        <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>\n        <AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"'$(Cfg_2)'!=''\">\n        <DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>\n        <DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>\n        <DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>\n        <DCC_DebugInformation>0</DCC_DebugInformation>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"'$(Cfg_2_Win32)'!=''\">\n        <AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>\n        <AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode>\n    </PropertyGroup>\n    <ItemGroup>\n        <DelphiCompile Include=\"$(MainSource)\">\n            <MainSource>MainSource</MainSource>\n        </DelphiCompile>\n        <DCCReference Include=\"uMain.pas\">\n            <Form>Main</Form>\n            <FormType>dfm</FormType>\n        </DCCReference>\n        <DCCReference Include=\"..\\..\\..\\Source\\CPUID.pas\"/>\n        <DCCReference Include=\"..\\..\\..\\Source\\DDetours.pas\"/>\n        <DCCReference Include=\"..\\..\\..\\Source\\InstDecode.pas\"/>\n        <DCCReference Include=\"..\\..\\..\\Source\\LegacyTypes.pas\"/>\n        <BuildConfiguration Include=\"Release\">\n            <Key>Cfg_2</Key>\n            <CfgParent>Base</CfgParent>\n        </BuildConfiguration>\n        <BuildConfiguration Include=\"Base\">\n            <Key>Base</Key>\n        </BuildConfiguration>\n        <BuildConfiguration Include=\"Debug\">\n            <Key>Cfg_1</Key>\n            <CfgParent>Base</CfgParent>\n        </BuildConfiguration>\n    </ItemGroup>\n    <ProjectExtensions>\n        <Borland.Personality>Delphi.Personality.12</Borland.Personality>\n        <Borland.ProjectType>Application</Borland.ProjectType>\n        <BorlandProject>\n            <Delphi.Personality>\n                <Source>\n                    <Source Name=\"MainSource\">Demo1.dpr</Source>\n                </Source>\n            </Delphi.Personality>\n            <Deployment Version=\"3\">\n                <DeployFile LocalName=\"Win32\\Debug\\Demo1.exe\" Configuration=\"Debug\" Class=\"ProjectOutput\">\n                    <Platform Name=\"Win32\">\n                        <RemoteName>Demo1.exe</RemoteName>\n                        <Overwrite>true</Overwrite>\n                    </Platform>\n                </DeployFile>\n                <DeployClass Name=\"AdditionalDebugSymbols\">\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"OSX32\">\n                        <RemoteDir>Contents\\MacOS</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"Win32\">\n                        <Operation>0</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"AndroidClassesDexFile\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>classes</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"AndroidFileProvider\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\xml</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"AndroidGDBServer\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>library\\lib\\armeabi-v7a</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"AndroidLibnativeArmeabiFile\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>library\\lib\\armeabi</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"AndroidLibnativeMipsFile\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>library\\lib\\mips</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"AndroidServiceOutput\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>library\\lib\\armeabi-v7a</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"AndroidSplashImageDef\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"AndroidSplashStyles\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\values</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"AndroidSplashStylesV21\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\values-v21</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_Colors\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\values</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_DefaultAppIcon\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_LauncherIcon144\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-xxhdpi</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_LauncherIcon36\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-ldpi</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_LauncherIcon48\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-mdpi</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_LauncherIcon72\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-hdpi</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_LauncherIcon96\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-xhdpi</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_NotificationIcon24\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-mdpi</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_NotificationIcon36\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-hdpi</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_NotificationIcon48\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-xhdpi</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_NotificationIcon72\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-xxhdpi</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_NotificationIcon96\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-xxxhdpi</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_SplashImage426\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-small</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_SplashImage470\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-normal</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_SplashImage640\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-large</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_SplashImage960\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-xlarge</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_Strings\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\values</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"DebugSymbols\">\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"OSX32\">\n                        <RemoteDir>Contents\\MacOS</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"Win32\">\n                        <Operation>0</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"DependencyFramework\">\n                    <Platform Name=\"OSX32\">\n                        <RemoteDir>Contents\\MacOS</RemoteDir>\n                        <Operation>1</Operation>\n                        <Extensions>.framework</Extensions>\n                    </Platform>\n                    <Platform Name=\"OSX64\">\n                        <RemoteDir>Contents\\MacOS</RemoteDir>\n                        <Operation>1</Operation>\n                        <Extensions>.framework</Extensions>\n                    </Platform>\n                    <Platform Name=\"Win32\">\n                        <Operation>0</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"DependencyModule\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                        <Extensions>.dylib</Extensions>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                        <Extensions>.dylib</Extensions>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                        <Extensions>.dylib</Extensions>\n                    </Platform>\n                    <Platform Name=\"OSX32\">\n                        <RemoteDir>Contents\\MacOS</RemoteDir>\n                        <Operation>1</Operation>\n                        <Extensions>.dylib</Extensions>\n                    </Platform>\n                    <Platform Name=\"OSX64\">\n                        <RemoteDir>Contents\\MacOS</RemoteDir>\n                        <Operation>1</Operation>\n                        <Extensions>.dylib</Extensions>\n                    </Platform>\n                    <Platform Name=\"Win32\">\n                        <Operation>0</Operation>\n                        <Extensions>.dll;.bpl</Extensions>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Required=\"true\" Name=\"DependencyPackage\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                        <Extensions>.dylib</Extensions>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                        <Extensions>.dylib</Extensions>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                        <Extensions>.dylib</Extensions>\n                    </Platform>\n                    <Platform Name=\"OSX32\">\n                        <RemoteDir>Contents\\MacOS</RemoteDir>\n                        <Operation>1</Operation>\n                        <Extensions>.dylib</Extensions>\n                    </Platform>\n                    <Platform Name=\"OSX64\">\n                        <RemoteDir>Contents\\MacOS</RemoteDir>\n                        <Operation>1</Operation>\n                        <Extensions>.dylib</Extensions>\n                    </Platform>\n                    <Platform Name=\"Win32\">\n                        <Operation>0</Operation>\n                        <Extensions>.bpl</Extensions>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"File\">\n                    <Platform Name=\"Android\">\n                        <Operation>0</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>0</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>0</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>0</Operation>\n                    </Platform>\n                    <Platform Name=\"OSX32\">\n                        <RemoteDir>Contents\\Resources\\StartUp\\</RemoteDir>\n                        <Operation>0</Operation>\n                    </Platform>\n                    <Platform Name=\"OSX64\">\n                        <RemoteDir>Contents\\Resources\\StartUp\\</RemoteDir>\n                        <Operation>0</Operation>\n                    </Platform>\n                    <Platform Name=\"Win32\">\n                        <Operation>0</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPad_Launch1024x768\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPad_Launch1536x2048\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPad_Launch1668\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPad_Launch1668x2388\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPad_Launch2048x1536\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPad_Launch2048x2732\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPad_Launch2224\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPad_Launch2388x1668\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPad_Launch2732x2048\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPad_Launch768x1024\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch1125\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch1136x640\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch1242\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch1242x2688\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch1334\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch1792\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch2208\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch2436\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch2688x1242\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch320\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch640\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch640x1136\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch750\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch828\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"ProjectAndroidManifest\">\n                    <Platform Name=\"Android\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"ProjectiOSDeviceDebug\">\n                    <Platform Name=\"iOSDevice32\">\n                        <RemoteDir>..\\$(PROJECTNAME).app.dSYM\\Contents\\Resources\\DWARF</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <RemoteDir>..\\$(PROJECTNAME).app.dSYM\\Contents\\Resources\\DWARF</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"ProjectiOSDeviceResourceRules\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"ProjectiOSEntitlements\">\n                    <Platform Name=\"iOSDevice32\">\n                        <RemoteDir>..\\</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <RemoteDir>..\\</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"ProjectiOSInfoPList\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"ProjectiOSResource\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"ProjectOSXDebug\">\n                    <Platform Name=\"OSX64\">\n                        <RemoteDir>..\\$(PROJECTNAME).app.dSYM\\Contents\\Resources\\DWARF</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"ProjectOSXEntitlements\">\n                    <Platform Name=\"OSX32\">\n                        <RemoteDir>..\\</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"OSX64\">\n                        <RemoteDir>..\\</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"ProjectOSXInfoPList\">\n                    <Platform Name=\"OSX32\">\n                        <RemoteDir>Contents</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"OSX64\">\n                        <RemoteDir>Contents</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"ProjectOSXResource\">\n                    <Platform Name=\"OSX32\">\n                        <RemoteDir>Contents\\Resources</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"OSX64\">\n                        <RemoteDir>Contents\\Resources</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Required=\"true\" Name=\"ProjectOutput\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>library\\lib\\armeabi-v7a</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"Linux64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"OSX32\">\n                        <RemoteDir>Contents\\MacOS</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"OSX64\">\n                        <RemoteDir>Contents\\MacOS</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"Win32\">\n                        <Operation>0</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"ProjectUWPManifest\">\n                    <Platform Name=\"Win32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"Win64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"UWP_DelphiLogo150\">\n                    <Platform Name=\"Win32\">\n                        <RemoteDir>Assets</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"Win64\">\n                        <RemoteDir>Assets</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"UWP_DelphiLogo44\">\n                    <Platform Name=\"Win32\">\n                        <RemoteDir>Assets</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"Win64\">\n                        <RemoteDir>Assets</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <ProjectRoot Platform=\"iOSDevice64\" Name=\"$(PROJECTNAME).app\"/>\n                <ProjectRoot Platform=\"Win64\" Name=\"$(PROJECTNAME)\"/>\n                <ProjectRoot Platform=\"iOSDevice32\" Name=\"$(PROJECTNAME).app\"/>\n                <ProjectRoot Platform=\"Linux64\" Name=\"$(PROJECTNAME)\"/>\n                <ProjectRoot Platform=\"Win32\" Name=\"$(PROJECTNAME)\"/>\n                <ProjectRoot Platform=\"OSX32\" Name=\"$(PROJECTNAME).app\"/>\n                <ProjectRoot Platform=\"Android\" Name=\"$(PROJECTNAME)\"/>\n                <ProjectRoot Platform=\"OSX64\" Name=\"$(PROJECTNAME).app\"/>\n                <ProjectRoot Platform=\"iOSSimulator\" Name=\"$(PROJECTNAME).app\"/>\n            </Deployment>\n            <Platforms>\n                <Platform value=\"Win32\">True</Platform>\n                <Platform value=\"Win64\">False</Platform>\n            </Platforms>\n        </BorlandProject>\n        <ProjectFileVersion>12</ProjectFileVersion>\n    </ProjectExtensions>\n    <Import Project=\"$(BDS)\\Bin\\CodeGear.Delphi.Targets\" Condition=\"Exists('$(BDS)\\Bin\\CodeGear.Delphi.Targets')\"/>\n    <Import Project=\"$(APPDATA)\\Embarcadero\\$(BDSAPPDATABASEDIR)\\$(PRODUCTVERSION)\\UserTools.proj\" Condition=\"Exists('$(APPDATA)\\Embarcadero\\$(BDSAPPDATABASEDIR)\\$(PRODUCTVERSION)\\UserTools.proj')\"/>\n    <Import Project=\"$(MSBuildProjectName).deployproj\" Condition=\"Exists('$(MSBuildProjectName).deployproj')\"/>\n</Project>\n"
  },
  {
    "path": "Demo/Delphi/Demo1/uMain.dfm",
    "content": "object Main: TMain\n  Left = 0\n  Top = 0\n  BorderStyle = bsToolWindow\n  Caption = 'Main'\n  ClientHeight = 134\n  ClientWidth = 257\n  Color = clBtnFace\n  Font.Charset = DEFAULT_CHARSET\n  Font.Color = clWindowText\n  Font.Height = -11\n  Font.Name = 'Tahoma'\n  Font.Style = []\n  OldCreateOrder = False\n  OnCreate = FormCreate\n  PixelsPerInch = 96\n  TextHeight = 13\n  object BtnHook: TButton\n    Left = 48\n    Top = 16\n    Width = 161\n    Height = 25\n    Caption = 'Hook'\n    TabOrder = 0\n    OnClick = BtnHookClick\n  end\n  object BtnMsgBox: TButton\n    Left = 48\n    Top = 55\n    Width = 161\n    Height = 25\n    Caption = 'MessageBox'\n    TabOrder = 1\n    OnClick = BtnMsgBoxClick\n  end\n  object BtnUnHook: TButton\n    Left = 48\n    Top = 91\n    Width = 161\n    Height = 25\n    Caption = 'Unhook'\n    TabOrder = 2\n    OnClick = BtnUnHookClick\n  end\nend\n"
  },
  {
    "path": "Demo/Delphi/Demo1/uMain.pas",
    "content": "unit uMain;\n\ninterface\n\nuses\n  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,\n  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, DDetours;\n\ntype\n  TMain = class(TForm)\n    BtnHook: TButton;\n    BtnMsgBox: TButton;\n    BtnUnHook: TButton;\n    procedure BtnHookClick(Sender: TObject);\n    procedure BtnUnHookClick(Sender: TObject);\n    procedure BtnMsgBoxClick(Sender: TObject);\n    procedure FormCreate(Sender: TObject);\n  private\n    { Private declarations }\n  public\n    { Public declarations }\n  end;\n\nvar\n  Main: TMain;\n\nimplementation\n\n{$R *.dfm}\n\ntype\n  TMessageBox = function(hWnd: hWnd; lpText, lpCaption: LPCWSTR; uType: UINT): Integer; stdcall;\n\nvar\n  TrampolineMessageBox: TMessageBox = nil;\n\nfunction InterceptMessageBox(hWnd: hWnd; lpText, lpCaption: LPCWSTR; uType: UINT): Integer; stdcall;\nvar\n  Self: TMain;\nbegin\n  Self := GetTrampolineParam(TrampolineMessageBox);\n  Self.Caption := 'MessageBox hooked !';\n  Result := TrampolineMessageBox(hWnd, 'this text was hooked', 'this title was hooked', MB_ICONWARNING);\nend;\n\nprocedure TMain.FormCreate(Sender: TObject);\nbegin\n  BtnUnHook.Enabled := False;\nend;\n\nprocedure TMain.BtnHookClick(Sender: TObject);\nbegin\n  TrampolineMessageBox := InterceptCreate(@MessageBox, @InterceptMessageBox, Self);\n  BtnUnHook.Enabled := True;\n  BtnHook.Enabled := False;\nend;\n\nprocedure TMain.BtnMsgBoxClick(Sender: TObject);\nbegin\n  MessageBox(0, 'text', 'caption', 0);\nend;\n\nprocedure TMain.BtnUnHookClick(Sender: TObject);\nbegin\n  if Assigned(TrampolineMessageBox) then\n  begin\n    InterceptRemove(@TrampolineMessageBox);\n    TrampolineMessageBox := nil;\n    BtnHook.Enabled := True;\n    BtnUnHook.Enabled := False;\n  end;\nend;\n\ninitialization\n\nfinalization\n\nif Assigned(TrampolineMessageBox) then\n  InterceptRemove(@TrampolineMessageBox);\n\nend.\n"
  },
  {
    "path": "Demo/Lazarus/Demo1/Demo1.lpi",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<CONFIG>\n  <ProjectOptions>\n    <Version Value=\"11\"/>\n    <PathDelim Value=\"\\\"/>\n    <General>\n      <SessionStorage Value=\"InProjectDir\"/>\n      <MainUnit Value=\"0\"/>\n      <Title Value=\"Demo1\"/>\n      <Scaled Value=\"True\"/>\n      <ResourceType Value=\"res\"/>\n      <UseXPManifest Value=\"True\"/>\n      <XPManifest>\n        <DpiAware Value=\"True\"/>\n      </XPManifest>\n      <Icon Value=\"0\"/>\n    </General>\n    <BuildModes Count=\"1\">\n      <Item1 Name=\"Default\" Default=\"True\"/>\n    </BuildModes>\n    <PublishOptions>\n      <Version Value=\"2\"/>\n      <UseFileFilters Value=\"True\"/>\n    </PublishOptions>\n    <RunParams>\n      <FormatVersion Value=\"2\"/>\n      <Modes Count=\"0\"/>\n    </RunParams>\n    <RequiredPackages Count=\"1\">\n      <Item1>\n        <PackageName Value=\"LCL\"/>\n      </Item1>\n    </RequiredPackages>\n    <Units Count=\"2\">\n      <Unit0>\n        <Filename Value=\"Demo1.lpr\"/>\n        <IsPartOfProject Value=\"True\"/>\n      </Unit0>\n      <Unit1>\n        <Filename Value=\"umain.pas\"/>\n        <IsPartOfProject Value=\"True\"/>\n        <ComponentName Value=\"Main\"/>\n        <HasResources Value=\"True\"/>\n        <ResourceBaseClass Value=\"Form\"/>\n        <UnitName Value=\"uMain\"/>\n      </Unit1>\n    </Units>\n  </ProjectOptions>\n  <CompilerOptions>\n    <Version Value=\"11\"/>\n    <PathDelim Value=\"\\\"/>\n    <Target>\n      <Filename Value=\"Demo1\"/>\n    </Target>\n    <SearchPaths>\n      <IncludeFiles Value=\"$(ProjOutDir)\"/>\n      <OtherUnitFiles Value=\"..\\..\\..\\Source\"/>\n      <UnitOutputDirectory Value=\"lib\\$(TargetCPU)-$(TargetOS)\"/>\n    </SearchPaths>\n    <Linking>\n      <Options>\n        <Win32>\n          <GraphicApplication Value=\"True\"/>\n        </Win32>\n      </Options>\n    </Linking>\n  </CompilerOptions>\n  <Debugging>\n    <Exceptions Count=\"3\">\n      <Item1>\n        <Name Value=\"EAbort\"/>\n      </Item1>\n      <Item2>\n        <Name Value=\"ECodetoolError\"/>\n      </Item2>\n      <Item3>\n        <Name Value=\"EFOpenError\"/>\n      </Item3>\n    </Exceptions>\n  </Debugging>\n</CONFIG>\n"
  },
  {
    "path": "Demo/Lazarus/Demo1/Demo1.lpr",
    "content": "program Demo1;\n\n{$mode objfpc}{$H+}\n\nuses\n  {$IFDEF UNIX}{$IFDEF UseCThreads}\n  cthreads,\n  {$ENDIF}{$ENDIF}\n  Interfaces, // this includes the LCL widgetset\n  Forms, uMain\n  { you can add units after this };\n\n{$R *.res}\n\nbegin\n  RequireDerivedFormResource:=True;\n  Application.Scaled:=True;\n  Application.Initialize;\n  Application.CreateForm(TMain, Main);\n  Application.Run;\nend.\n\n"
  },
  {
    "path": "Demo/Lazarus/Demo1/Demo1.lps",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<CONFIG>\n  <ProjectSession>\n    <PathDelim Value=\"\\\"/>\n    <Version Value=\"11\"/>\n    <BuildModes Active=\"Default\"/>\n    <Units Count=\"4\">\n      <Unit0>\n        <Filename Value=\"Demo1.lpr\"/>\n        <IsPartOfProject Value=\"True\"/>\n        <EditorIndex Value=\"-1\"/>\n        <WindowIndex Value=\"-1\"/>\n        <TopLine Value=\"-1\"/>\n        <CursorPos X=\"-1\" Y=\"-1\"/>\n        <UsageCount Value=\"20\"/>\n      </Unit0>\n      <Unit1>\n        <Filename Value=\"umain.pas\"/>\n        <IsPartOfProject Value=\"True\"/>\n        <ComponentName Value=\"Main\"/>\n        <HasResources Value=\"True\"/>\n        <ResourceBaseClass Value=\"Form\"/>\n        <UnitName Value=\"uMain\"/>\n        <IsVisibleTab Value=\"True\"/>\n        <TopLine Value=\"40\"/>\n        <CursorPos X=\"38\" Y=\"50\"/>\n        <UsageCount Value=\"20\"/>\n        <Loaded Value=\"True\"/>\n        <LoadedDesigner Value=\"True\"/>\n      </Unit1>\n      <Unit2>\n        <Filename Value=\"C:\\lazarus\\fpc\\3.0.4\\source\\rtl\\win\\wininc\\ascdef.inc\"/>\n        <EditorIndex Value=\"2\"/>\n        <TopLine Value=\"248\"/>\n        <CursorPos Y=\"257\"/>\n        <UsageCount Value=\"10\"/>\n        <Loaded Value=\"True\"/>\n      </Unit2>\n      <Unit3>\n        <Filename Value=\"..\\..\\..\\Source\\DDetours.pas\"/>\n        <EditorIndex Value=\"1\"/>\n        <TopLine Value=\"2291\"/>\n        <CursorPos Y=\"2299\"/>\n        <UsageCount Value=\"10\"/>\n        <Loaded Value=\"True\"/>\n      </Unit3>\n    </Units>\n    <JumpHistory Count=\"21\" HistoryIndex=\"20\">\n      <Position1>\n        <Filename Value=\"umain.pas\"/>\n      </Position1>\n      <Position2>\n        <Filename Value=\"umain.pas\"/>\n        <Caret Line=\"37\" Column=\"21\" TopLine=\"25\"/>\n      </Position2>\n      <Position3>\n        <Filename Value=\"umain.pas\"/>\n        <Caret Line=\"34\" Column=\"28\" TopLine=\"24\"/>\n      </Position3>\n      <Position4>\n        <Filename Value=\"umain.pas\"/>\n        <Caret Line=\"50\" Column=\"6\" TopLine=\"37\"/>\n      </Position4>\n      <Position5>\n        <Filename Value=\"umain.pas\"/>\n        <Caret Line=\"9\" Column=\"20\"/>\n      </Position5>\n      <Position6>\n        <Filename Value=\"umain.pas\"/>\n        <Caret Line=\"49\" TopLine=\"39\"/>\n      </Position6>\n      <Position7>\n        <Filename Value=\"umain.pas\"/>\n        <Caret Line=\"68\" Column=\"42\" TopLine=\"53\"/>\n      </Position7>\n      <Position8>\n        <Filename Value=\"umain.pas\"/>\n        <Caret Line=\"53\" Column=\"5\" TopLine=\"44\"/>\n      </Position8>\n      <Position9>\n        <Filename Value=\"umain.pas\"/>\n        <Caret Line=\"61\" Column=\"9\" TopLine=\"45\"/>\n      </Position9>\n      <Position10>\n        <Filename Value=\"umain.pas\"/>\n        <Caret Line=\"53\" Column=\"5\" TopLine=\"45\"/>\n      </Position10>\n      <Position11>\n        <Filename Value=\"umain.pas\"/>\n        <Caret Line=\"56\" Column=\"51\" TopLine=\"45\"/>\n      </Position11>\n      <Position12>\n        <Filename Value=\"umain.pas\"/>\n        <Caret Line=\"53\" Column=\"54\" TopLine=\"45\"/>\n      </Position12>\n      <Position13>\n        <Filename Value=\"umain.pas\"/>\n        <Caret Line=\"4\" Column=\"2\"/>\n      </Position13>\n      <Position14>\n        <Filename Value=\"umain.pas\"/>\n        <Caret Line=\"69\" Column=\"20\" TopLine=\"54\"/>\n      </Position14>\n      <Position15>\n        <Filename Value=\"umain.pas\"/>\n        <Caret Line=\"70\" Column=\"35\" TopLine=\"54\"/>\n      </Position15>\n      <Position16>\n        <Filename Value=\"umain.pas\"/>\n        <Caret Line=\"75\" Column=\"21\" TopLine=\"59\"/>\n      </Position16>\n      <Position17>\n        <Filename Value=\"umain.pas\"/>\n        <Caret Line=\"74\" TopLine=\"60\"/>\n      </Position17>\n      <Position18>\n        <Filename Value=\"umain.pas\"/>\n        <Caret Line=\"75\" TopLine=\"60\"/>\n      </Position18>\n      <Position19>\n        <Filename Value=\"umain.pas\"/>\n        <Caret Line=\"74\" TopLine=\"60\"/>\n      </Position19>\n      <Position20>\n        <Filename Value=\"umain.pas\"/>\n        <Caret Line=\"80\" TopLine=\"64\"/>\n      </Position20>\n      <Position21>\n        <Filename Value=\"umain.pas\"/>\n        <Caret Line=\"48\" Column=\"25\" TopLine=\"35\"/>\n      </Position21>\n    </JumpHistory>\n    <RunParams>\n      <FormatVersion Value=\"2\"/>\n      <Modes Count=\"0\" ActiveMode=\"\"/>\n    </RunParams>\n  </ProjectSession>\n</CONFIG>\n"
  },
  {
    "path": "Demo/Lazarus/Demo1/umain.lfm",
    "content": "object Main: TMain\n  Left = 256\n  Height = 137\n  Top = 145\n  Width = 242\n  BorderStyle = bsToolWindow\n  Caption = 'Main'\n  ClientHeight = 137\n  ClientWidth = 242\n  OnCreate = FormCreate\n  LCLVersion = '2.0.8.0'\n  object BtnHook: TButton\n    Left = 49\n    Height = 27\n    Top = 23\n    Width = 141\n    Caption = 'Hook'\n    OnClick = BtnHookClick\n    TabOrder = 0\n  end\n  object BtnMsgBox: TButton\n    Left = 48\n    Height = 25\n    Top = 56\n    Width = 141\n    Caption = 'MessageBox'\n    OnClick = BtnMsgBoxClick\n    TabOrder = 1\n  end\n  object BtnUnhook: TButton\n    Left = 49\n    Height = 26\n    Top = 88\n    Width = 141\n    Caption = 'Unhook'\n    OnClick = BtnUnhookClick\n    TabOrder = 2\n  end\nend\n"
  },
  {
    "path": "Demo/Lazarus/Demo1/umain.pas",
    "content": "unit uMain;\n\n{$mode Delphi}{$H+}\n\n\ninterface\n\nuses\n  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls,\n  Windows, DDetours;\n\ntype\n\n  { TMain }\n\n  TMain = class(TForm)\n    BtnHook: TButton;\n    BtnMsgBox: TButton;\n    BtnUnhook: TButton;\n    procedure BtnHookClick(Sender: TObject);\n    procedure BtnMsgBoxClick(Sender: TObject);\n    procedure BtnUnhookClick(Sender: TObject);\n    procedure FormCreate(Sender: TObject);\n  private\n\n  public\n\n  end;\n\nvar\n  Main: TMain;\n\nimplementation\n\n{$R *.lfm}\n\ntype\n  TMessageBox = function(hWnd: HWND; lpText: LPCSTR; lpCaption: LPCSTR;\n    uType: UINT): longint; stdcall;\n\nvar\n  TrampolineMessageBox: TMessageBox = nil;\n\nfunction InterceptMessageBox(hWnd: HWND; lpText: LPCSTR; lpCaption: LPCSTR;\n  uType: UINT): longint; stdcall;\nvar\n  Form: TMain;\nbegin\n  Form := GetTrampolineParam(TrampolineMessageBox);\n  Form.Caption := 'MessageBox Hooked!';\n  Result := TrampolineMessageBox(hWnd, 'this text was hooked.',\n    'this caption was hooked.', MB_ICONEXCLAMATION);\nend;\n\n{ TMain }\n\nprocedure TMain.BtnHookClick(Sender: TObject);\nbegin\n  BtnUnhook.Enabled := True;\n  BtnHook.Enabled := False;\n  @TrampolineMessageBox := InterceptCreate(@MessageBox, @InterceptMessageBox, Self);\nend;\n\nprocedure TMain.BtnMsgBoxClick(Sender: TObject);\nbegin\n  MessageBox(0, 'text', 'caption', 0);\nend;\n\nprocedure TMain.BtnUnhookClick(Sender: TObject);\nbegin\n  BtnHook.Enabled := True;\n  BtnUnHook.Enabled := False;\n  if Assigned(TrampolineMessageBox) then\n  begin\n    InterceptRemove(@TrampolineMessageBox);\n    TrampolineMessageBox := nil;\n  end;\nend;\n\nprocedure TMain.FormCreate(Sender: TObject);\nbegin\n  BtnUnhook.Enabled := False;\nend;\n\ninitialization\n\nfinalization\n  if Assigned(TrampolineMessageBox) then\n    InterceptRemove(@TrampolineMessageBox);\nend.\n"
  },
  {
    "path": "LICENSE",
    "content": "Mozilla Public License Version 2.0\n==================================\n\n1. Definitions\n--------------\n\n1.1. \"Contributor\"\n    means each individual or legal entity that creates, contributes to\n    the creation of, or owns Covered Software.\n\n1.2. \"Contributor Version\"\n    means the combination of the Contributions of others (if any) used\n    by a Contributor and that particular Contributor's Contribution.\n\n1.3. \"Contribution\"\n    means Covered Software of a particular Contributor.\n\n1.4. \"Covered Software\"\n    means Source Code Form to which the initial Contributor has attached\n    the notice in Exhibit A, the Executable Form of such Source Code\n    Form, and Modifications of such Source Code Form, in each case\n    including portions thereof.\n\n1.5. \"Incompatible With Secondary Licenses\"\n    means\n\n    (a) that the initial Contributor has attached the notice described\n        in Exhibit B to the Covered Software; or\n\n    (b) that the Covered Software was made available under the terms of\n        version 1.1 or earlier of the License, but not also under the\n        terms of a Secondary License.\n\n1.6. \"Executable Form\"\n    means any form of the work other than Source Code Form.\n\n1.7. \"Larger Work\"\n    means a work that combines Covered Software with other material, in\n    a separate file or files, that is not Covered Software.\n\n1.8. \"License\"\n    means this document.\n\n1.9. \"Licensable\"\n    means having the right to grant, to the maximum extent possible,\n    whether at the time of the initial grant or subsequently, any and\n    all of the rights conveyed by this License.\n\n1.10. \"Modifications\"\n    means any of the following:\n\n    (a) any file in Source Code Form that results from an addition to,\n        deletion from, or modification of the contents of Covered\n        Software; or\n\n    (b) any new file in Source Code Form that contains any Covered\n        Software.\n\n1.11. \"Patent Claims\" of a Contributor\n    means any patent claim(s), including without limitation, method,\n    process, and apparatus claims, in any patent Licensable by such\n    Contributor that would be infringed, but for the grant of the\n    License, by the making, using, selling, offering for sale, having\n    made, import, or transfer of either its Contributions or its\n    Contributor Version.\n\n1.12. \"Secondary License\"\n    means either the GNU General Public License, Version 2.0, the GNU\n    Lesser General Public License, Version 2.1, the GNU Affero General\n    Public License, Version 3.0, or any later versions of those\n    licenses.\n\n1.13. \"Source Code Form\"\n    means the form of the work preferred for making modifications.\n\n1.14. \"You\" (or \"Your\")\n    means an individual or a legal entity exercising rights under this\n    License. For legal entities, \"You\" includes any entity that\n    controls, is controlled by, or is under common control with You. For\n    purposes of this definition, \"control\" means (a) the power, direct\n    or indirect, to cause the direction or management of such entity,\n    whether by contract or otherwise, or (b) ownership of more than\n    fifty percent (50%) of the outstanding shares or beneficial\n    ownership of such entity.\n\n2. License Grants and Conditions\n--------------------------------\n\n2.1. Grants\n\nEach Contributor hereby grants You a world-wide, royalty-free,\nnon-exclusive license:\n\n(a) under intellectual property rights (other than patent or trademark)\n    Licensable by such Contributor to use, reproduce, make available,\n    modify, display, perform, distribute, and otherwise exploit its\n    Contributions, either on an unmodified basis, with Modifications, or\n    as part of a Larger Work; and\n\n(b) under Patent Claims of such Contributor to make, use, sell, offer\n    for sale, have made, import, and otherwise transfer either its\n    Contributions or its Contributor Version.\n\n2.2. Effective Date\n\nThe licenses granted in Section 2.1 with respect to any Contribution\nbecome effective for each Contribution on the date the Contributor first\ndistributes such Contribution.\n\n2.3. Limitations on Grant Scope\n\nThe licenses granted in this Section 2 are the only rights granted under\nthis License. No additional rights or licenses will be implied from the\ndistribution or licensing of Covered Software under this License.\nNotwithstanding Section 2.1(b) above, no patent license is granted by a\nContributor:\n\n(a) for any code that a Contributor has removed from Covered Software;\n    or\n\n(b) for infringements caused by: (i) Your and any other third party's\n    modifications of Covered Software, or (ii) the combination of its\n    Contributions with other software (except as part of its Contributor\n    Version); or\n\n(c) under Patent Claims infringed by Covered Software in the absence of\n    its Contributions.\n\nThis License does not grant any rights in the trademarks, service marks,\nor logos of any Contributor (except as may be necessary to comply with\nthe notice requirements in Section 3.4).\n\n2.4. Subsequent Licenses\n\nNo Contributor makes additional grants as a result of Your choice to\ndistribute the Covered Software under a subsequent version of this\nLicense (see Section 10.2) or under the terms of a Secondary License (if\npermitted under the terms of Section 3.3).\n\n2.5. Representation\n\nEach Contributor represents that the Contributor believes its\nContributions are its original creation(s) or it has sufficient rights\nto grant the rights to its Contributions conveyed by this License.\n\n2.6. Fair Use\n\nThis License is not intended to limit any rights You have under\napplicable copyright doctrines of fair use, fair dealing, or other\nequivalents.\n\n2.7. Conditions\n\nSections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted\nin Section 2.1.\n\n3. Responsibilities\n-------------------\n\n3.1. Distribution of Source Form\n\nAll distribution of Covered Software in Source Code Form, including any\nModifications that You create or to which You contribute, must be under\nthe terms of this License. You must inform recipients that the Source\nCode Form of the Covered Software is governed by the terms of this\nLicense, and how they can obtain a copy of this License. You may not\nattempt to alter or restrict the recipients' rights in the Source Code\nForm.\n\n3.2. Distribution of Executable Form\n\nIf You distribute Covered Software in Executable Form then:\n\n(a) such Covered Software must also be made available in Source Code\n    Form, as described in Section 3.1, and You must inform recipients of\n    the Executable Form how they can obtain a copy of such Source Code\n    Form by reasonable means in a timely manner, at a charge no more\n    than the cost of distribution to the recipient; and\n\n(b) You may distribute such Executable Form under the terms of this\n    License, or sublicense it under different terms, provided that the\n    license for the Executable Form does not attempt to limit or alter\n    the recipients' rights in the Source Code Form under this License.\n\n3.3. Distribution of a Larger Work\n\nYou may create and distribute a Larger Work under terms of Your choice,\nprovided that You also comply with the requirements of this License for\nthe Covered Software. If the Larger Work is a combination of Covered\nSoftware with a work governed by one or more Secondary Licenses, and the\nCovered Software is not Incompatible With Secondary Licenses, this\nLicense permits You to additionally distribute such Covered Software\nunder the terms of such Secondary License(s), so that the recipient of\nthe Larger Work may, at their option, further distribute the Covered\nSoftware under the terms of either this License or such Secondary\nLicense(s).\n\n3.4. Notices\n\nYou may not remove or alter the substance of any license notices\n(including copyright notices, patent notices, disclaimers of warranty,\nor limitations of liability) contained within the Source Code Form of\nthe Covered Software, except that You may alter any license notices to\nthe extent required to remedy known factual inaccuracies.\n\n3.5. Application of Additional Terms\n\nYou may choose to offer, and to charge a fee for, warranty, support,\nindemnity or liability obligations to one or more recipients of Covered\nSoftware. However, You may do so only on Your own behalf, and not on\nbehalf of any Contributor. You must make it absolutely clear that any\nsuch warranty, support, indemnity, or liability obligation is offered by\nYou alone, and You hereby agree to indemnify every Contributor for any\nliability incurred by such Contributor as a result of warranty, support,\nindemnity or liability terms You offer. You may include additional\ndisclaimers of warranty and limitations of liability specific to any\njurisdiction.\n\n4. Inability to Comply Due to Statute or Regulation\n---------------------------------------------------\n\nIf it is impossible for You to comply with any of the terms of this\nLicense with respect to some or all of the Covered Software due to\nstatute, judicial order, or regulation then You must: (a) comply with\nthe terms of this License to the maximum extent possible; and (b)\ndescribe the limitations and the code they affect. Such description must\nbe placed in a text file included with all distributions of the Covered\nSoftware under this License. Except to the extent prohibited by statute\nor regulation, such description must be sufficiently detailed for a\nrecipient of ordinary skill to be able to understand it.\n\n5. Termination\n--------------\n\n5.1. The rights granted under this License will terminate automatically\nif You fail to comply with any of its terms. However, if You become\ncompliant, then the rights granted under this License from a particular\nContributor are reinstated (a) provisionally, unless and until such\nContributor explicitly and finally terminates Your grants, and (b) on an\nongoing basis, if such Contributor fails to notify You of the\nnon-compliance by some reasonable means prior to 60 days after You have\ncome back into compliance. Moreover, Your grants from a particular\nContributor are reinstated on an ongoing basis if such Contributor\nnotifies You of the non-compliance by some reasonable means, this is the\nfirst time You have received notice of non-compliance with this License\nfrom such Contributor, and You become compliant prior to 30 days after\nYour receipt of the notice.\n\n5.2. If You initiate litigation against any entity by asserting a patent\ninfringement claim (excluding declaratory judgment actions,\ncounter-claims, and cross-claims) alleging that a Contributor Version\ndirectly or indirectly infringes any patent, then the rights granted to\nYou by any and all Contributors for the Covered Software under Section\n2.1 of this License shall terminate.\n\n5.3. In the event of termination under Sections 5.1 or 5.2 above, all\nend user license agreements (excluding distributors and resellers) which\nhave been validly granted by You or Your distributors under this License\nprior to termination shall survive termination.\n\n************************************************************************\n*                                                                      *\n*  6. Disclaimer of Warranty                                           *\n*  -------------------------                                           *\n*                                                                      *\n*  Covered Software is provided under this License on an \"as is\"       *\n*  basis, without warranty of any kind, either expressed, implied, or  *\n*  statutory, including, without limitation, warranties that the       *\n*  Covered Software is free of defects, merchantable, fit for a        *\n*  particular purpose or non-infringing. The entire risk as to the     *\n*  quality and performance of the Covered Software is with You.        *\n*  Should any Covered Software prove defective in any respect, You     *\n*  (not any Contributor) assume the cost of any necessary servicing,   *\n*  repair, or correction. This disclaimer of warranty constitutes an   *\n*  essential part of this License. No use of any Covered Software is   *\n*  authorized under this License except under this disclaimer.         *\n*                                                                      *\n************************************************************************\n\n************************************************************************\n*                                                                      *\n*  7. Limitation of Liability                                          *\n*  --------------------------                                          *\n*                                                                      *\n*  Under no circumstances and under no legal theory, whether tort      *\n*  (including negligence), contract, or otherwise, shall any           *\n*  Contributor, or anyone who distributes Covered Software as          *\n*  permitted above, be liable to You for any direct, indirect,         *\n*  special, incidental, or consequential damages of any character      *\n*  including, without limitation, damages for lost profits, loss of    *\n*  goodwill, work stoppage, computer failure or malfunction, or any    *\n*  and all other commercial damages or losses, even if such party      *\n*  shall have been informed of the possibility of such damages. This   *\n*  limitation of liability shall not apply to liability for death or   *\n*  personal injury resulting from such party's negligence to the       *\n*  extent applicable law prohibits such limitation. Some               *\n*  jurisdictions do not allow the exclusion or limitation of           *\n*  incidental or consequential damages, so this exclusion and          *\n*  limitation may not apply to You.                                    *\n*                                                                      *\n************************************************************************\n\n8. Litigation\n-------------\n\nAny litigation relating to this License may be brought only in the\ncourts of a jurisdiction where the defendant maintains its principal\nplace of business and such litigation shall be governed by laws of that\njurisdiction, without reference to its conflict-of-law provisions.\nNothing in this Section shall prevent a party's ability to bring\ncross-claims or counter-claims.\n\n9. Miscellaneous\n----------------\n\nThis License represents the complete agreement concerning the subject\nmatter hereof. If any provision of this License is held to be\nunenforceable, such provision shall be reformed only to the extent\nnecessary to make it enforceable. Any law or regulation which provides\nthat the language of a contract shall be construed against the drafter\nshall not be used to construe this License against a Contributor.\n\n10. Versions of the License\n---------------------------\n\n10.1. New Versions\n\nMozilla Foundation is the license steward. Except as provided in Section\n10.3, no one other than the license steward has the right to modify or\npublish new versions of this License. Each version will be given a\ndistinguishing version number.\n\n10.2. Effect of New Versions\n\nYou may distribute the Covered Software under the terms of the version\nof the License under which You originally received the Covered Software,\nor under the terms of any subsequent version published by the license\nsteward.\n\n10.3. Modified Versions\n\nIf you create software not governed by this License, and you want to\ncreate a new license for such software, you may create and use a\nmodified version of this License if you rename the license and remove\nany references to the name of the license steward (except to note that\nsuch modified license differs from this License).\n\n10.4. Distributing Source Code Form that is Incompatible With Secondary\nLicenses\n\nIf You choose to distribute Source Code Form that is Incompatible With\nSecondary Licenses under the terms of this version of the License, the\nnotice described in Exhibit B of this License must be attached.\n\nExhibit A - Source Code Form License Notice\n-------------------------------------------\n\n  This Source Code Form is subject to the terms of the Mozilla Public\n  License, v. 2.0. If a copy of the MPL was not distributed with this\n  file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nIf it is not possible or desirable to put the notice in a particular\nfile, then You may include the notice in a location (such as a LICENSE\nfile in a relevant directory) where a recipient would be likely to look\nfor such a notice.\n\nYou may add additional accurate notices of copyright ownership.\n\nExhibit B - \"Incompatible With Secondary Licenses\" Notice\n---------------------------------------------------------\n\n  This Source Code Form is \"Incompatible With Secondary Licenses\", as\n  defined by the Mozilla Public License, v. 2.0.\n"
  },
  {
    "path": "README.md",
    "content": "![Version](https://img.shields.io/badge/version-v2.2-yellow.svg)\n![License](https://img.shields.io/github/license/MahdiSafsafi/DDetours)\n![Lang](https://img.shields.io/github/languages/top/MahdiSafsafi/DDetours.svg)\n\nThe **DDetours** is a library allowing you to hook Delphi and Windows API functions. It provides an easy way to insert and remove hook.\n\n## What's new in Version 2.2 ? ##\n* Support for FPC and older Delphi version notably D7.\n* Support for recursive section.\n* Support for custom parameter/tag for each trampoline function.\n* See CHANGELOG for complete changes.\n\n## Features : ##\n* Supports **x86** and **x64** architecture.\n* Supports <u><b>multiple hook</b></u> for a single function.\n* Supports Delphi 7/2005-2010/XE-Rio(Delphi 10.3).\n* Supports Lazarus/FPC.\n* Supports recursive function inside the hook function.\n* Supports hooking interfaces methods by **MethodName** or **MethodIndex**.\n* Supports COM **vtable** patching.\n* Supports hooking object methods.\n* Allows calling the original function via <u><b>Trampoline/NextHook</b></u> function.\n* **COM**/**Interfaces**/**win32api** support.\n* Thread-safe for hooking and unhooking.\n* 64 bit address is supported.\n* The library does not use any external library.\n* The library can insert and remove the hook at any time.\n* The library contains InstDecode library, that allows you to decode CPU instructions (x86/x64).\n\nThis project contains two sub project : **DDetours** and **InstDecode*** library.\n\nThe InstDecode Library is a library that can decode both (x86/x64) instructions. You can consider it as a small disassembler routine.\nIt can decode instruction and getting information about the instruction (size of instruction, displacement, immediate data, jump address,..) without displaying mnemonics making it very faster and very small in size.\n\nThese two libraries were coded in pure Pascal language with Delphi XE7.\n\nSee the [Wiki](https://github.com/MahdiSafsafi/DDetours/wiki) page for more information about how to use the library.\n\nPlease, if you find any bug, feel free to report it.\n"
  },
  {
    "path": "Source/CPUID.pas",
    "content": "// **************************************************************************************************\n// CPUID for Delphi.\n// Unit CPUID\n// https://github.com/MahdiSafsafi/DDetours\n//\n// This Source Code Form is subject to the terms of the Mozilla \n// Public License, v. 2.0. If a copy of the MPL was not distributed \n// with this file, You can obtain one at\n// https://mozilla.org/MPL/2.0/.\n// **************************************************************************************************\n\nunit CPUID;\n{$IFDEF FPC}\n{$MODE DELPHI}\n{$WARN 4055 OFF}\n{$WARN 4082 OFF}\n{$WARN 5057 OFF}\n{$ENDIF FPC}\n\ninterface\n\n{$I DDetoursDefs.inc}\n\nuses\n  SysUtils\n{$IFNDEF FPC}, LegacyTypes{$ENDIF FPC}\n    ;\n\ntype\n  { Do not change registers order ! }\n  TCPUIDStruct = packed record\n    rEAX: Cardinal; { EAX Register }\n    rEBX: Cardinal; { EBX Register }\n    rEDX: Cardinal; { EDX Register }\n    rECX: Cardinal; { ECX Register }\n  end;\n\n  PCPUIDStruct = ^TCPUIDStruct;\n\nprocedure CallCPUID(ID: NativeUInt; var CPUIDStruct: TCPUIDStruct);\nfunction IsCPUIDSupported(): Boolean;\n\ntype\n  TCPUVendor = (vUnknown, vIntel, vAMD, vNextGen);\n  TCPUEncoding = set of (REX, VEX, EVEX);\n  TCPUInstructions = set of (iMultiNop);\n\nvar\n  CPUVendor: TCPUVendor;\n  CPUEncoding: TCPUEncoding;\n  CPUInsts: TCPUInstructions;\n\nimplementation\n\nvar\n  CPUIDSupported: Boolean = False;\n\nfunction ___IsCPUIDSupported: Boolean;\nasm\n  {$IFDEF CPUX64}\n  PUSH RCX\n  MOV RCX,RCX\n  PUSHFQ\n  POP RAX\n  MOV RCX, RAX\n  XOR RAX, $200000\n  PUSH RAX\n  POPFQ\n  PUSHFQ\n  POP RAX\n  XOR RAX, RCX\n  SHR RAX, 21\n  AND RAX, 1\n  PUSH RCX\n  POPFQ\n  POP RCX\n  {$ELSE !CPUX64}\n\n  PUSH ECX\n  PUSHFD\n  POP EAX { EAX = EFLAGS }\n  MOV ECX, EAX  { Save the original EFLAGS value . }\n  {\n  CPUID is supported only if we can modify\n  bit 21 of EFLAGS register !\n   }\n  XOR EAX, $200000\n  PUSH EAX\n  POPFD { Set the new EFLAGS value }\n  PUSHFD\n  POP EAX { Read EFLAGS }\n  {\n  Check if the 21 bit was modified !\n  If so ==> Return True .\n  else  ==> Return False.\n   }\n  XOR EAX, ECX\n  SHR EAX, 21\n  AND EAX, 1\n  PUSH ECX\n  POPFD  { Restore original EFLAGS value . }\n  POP ECX\n  {$ENDIF CPUX64}\nend;\n\nprocedure ___CallCPUID(const ID: NativeInt; var CPUIDStruct);\nasm\n  {\n  ALL REGISTERS (rDX,rCX,rBX) MUST BE SAVED BEFORE\n  EXECUTING CPUID INSTRUCTION !\n   }\n  {$IFDEF CPUX64}\n  PUSH R9\n  PUSH RBX\n  PUSH RDX\n  MOV RAX,RCX\n  MOV R9,RDX\n  CPUID\n  {$IFNDEF FPC}\n  MOV R9.TCPUIDStruct.rEAX,EAX\n  MOV R9.TCPUIDStruct.rEBX,EBX\n  MOV R9.TCPUIDStruct.rECX,ECX\n  MOV R9.TCPUIDStruct.rEDX,EDX\n  {$ELSE FPC}\n  MOV [R9].TCPUIDStruct.rEAX,EAX\n  MOV [R9].TCPUIDStruct.rEBX,EBX\n  MOV [R9].TCPUIDStruct.rECX,ECX\n  MOV [R9].TCPUIDStruct.rEDX,EDX\n  {$ENDIF !FPC}\n  POP RDX\n  POP RBX\n  POP R9\n  {$ELSE !CPUX64}\n\n  PUSH EDI\n  PUSH ECX\n  PUSH EBX\n  MOV EDI,EDX\n  CPUID\n  {$IFNDEF FPC}\n  MOV EDI.TCPUIDStruct.rEAX,EAX\n  MOV EDI.TCPUIDStruct.rEBX,EBX\n  MOV EDI.TCPUIDStruct.rECX,ECX\n  MOV EDI.TCPUIDStruct.rEDX,EDX\n  {$ELSE FPC}\n  MOV [EDI].TCPUIDStruct.rEAX,EAX\n  MOV [EDI].TCPUIDStruct.rEBX,EBX\n  MOV [EDI].TCPUIDStruct.rECX,ECX\n  MOV [EDI].TCPUIDStruct.rEDX,EDX\n  {$ENDIF !FPC}\n  POP EBX\n  POP ECX\n  POP EDI\n  {$ENDIF CPUX64}\nend;\n\nfunction ___IsAVXSupported: Boolean;\nasm\n  {\n  Checking for AVX support requires 3 steps:\n\n  1) Detect CPUID.1:ECX.OSXSAVE[bit 27] = 1\n  => XGETBV enabled for application use\n\n  2) Detect CPUID.1:ECX.AVX[bit 28] = 1\n  => AVX instructions supported.\n\n  3) Issue XGETBV and verify that XCR0[2:1] = ‘11b’\n  => XMM state and YMM state are enabled by OS.\n\n   }\n\n  { Steps : 1 and 2 }\n  {$IFDEF CPUX64}\n  MOV RAX, 1\n  PUSH RCX\n  PUSH RBX\n  PUSH RDX\n  {$ELSE !CPUX64}\n  MOV EAX, 1\n  PUSH ECX\n  PUSH EBX\n  PUSH EDX\n  {$ENDIF CPUX64}\n  CPUID\n  AND ECX, $018000000\n  CMP  ECX, $018000000\n  JNE  @@NOT_SUPPORTED\n  XOR  ECX,ECX\n  {\n  Delphi does not support XGETBV !\n  => We need to use the XGETBV opcodes !\n   }\n  DB $0F DB $01 DB $D0 // XGETBV\n  { Step :3 }\n  AND EAX, $06\n  CMP  EAX, $06\n  JNE @@NOT_SUPPORTED\n  MOV EAX, 1\n  JMP @@END\n@@NOT_SUPPORTED:\n  XOR EAX,EAX\n@@END:\n  {$IFDEF CPUX64}\n  POP RDX\n  POP RBX\n  POP RCX\n  {$ELSE !CPUX64}\n  POP EDX\n  POP EBX\n  POP ECX\n  {$ENDIF CPUX64}\nend;\n\nprocedure CallCPUID(ID: NativeUInt; var CPUIDStruct: TCPUIDStruct);\nbegin\n  FillChar(CPUIDStruct, SizeOf(TCPUIDStruct), #0);\n  if not CPUIDSupported then\n    raise Exception.Create('CPUID instruction not supported.')\n  else\n    ___CallCPUID(ID, CPUIDStruct);\nend;\n\nfunction IsCPUIDSupported: Boolean;\nbegin\n  Result := CPUIDSupported;\nend;\n\ntype\n  TVendorName = array [0 .. 12] of AnsiChar;\n\nfunction GetVendorName(): TVendorName;\nvar\n  Info: PCPUIDStruct;\n  P: PByte;\nbegin\n  Result := '';\n  if not IsCPUIDSupported then\n    Exit;\n  Info := GetMemory(SizeOf(TCPUIDStruct));\n  CallCPUID(0, Info^);\n  P := PByte(NativeInt(Info) + 4); // Skip EAX !\n  Move(P^, PByte(@Result[0])^, 12);\n  FreeMemory(Info);\nend;\n\nprocedure __Init__;\nvar\n  vn: TVendorName;\n  Info: TCPUIDStruct;\n  r: Cardinal;\nbegin\n  CPUVendor := vUnknown;\n{$IFDEF CPUX64}\n  CPUEncoding := [REX];\n{$ELSE !CPUX64}\n  CPUEncoding := [];\n{$ENDIF CPUX64}\n  CPUInsts := [];\n  if IsCPUIDSupported then\n  begin\n    vn := GetVendorName();\n    if vn = 'GenuineIntel' then\n      CPUVendor := vIntel\n    else if vn = 'AuthenticAMD' then\n      CPUVendor := vAMD\n    else if vn = 'NexGenDriven' then\n      CPUVendor := vNextGen;\n    CallCPUID(1, Info);\n    r := Info.rEAX and $F00;\n    case r of\n      $F00, $600:\n        Include(CPUInsts, iMultiNop);\n    end;\n    if ___IsAVXSupported then\n      Include(CPUEncoding, VEX);\n  end;\nend;\n\ninitialization\n\nCPUIDSupported := ___IsCPUIDSupported;\n__Init__;\n\nend.\n"
  },
  {
    "path": "Source/DDetours.pas",
    "content": "// **************************************************************************************************\n// Delphi Detours Library.\n// Unit DDetours\n// https://github.com/MahdiSafsafi/DDetours\n//\n// This Source Code Form is subject to the terms of the Mozilla\n// Public License, v. 2.0. If a copy of the MPL was not distributed\n// with this file, You can obtain one at\n// https://mozilla.org/MPL/2.0/.\n// **************************************************************************************************\n//\n// Contributors:\n// - David Millington : Added TDetours<T> class.\n// **************************************************************************************************\n\nunit DDetours;\n\n{define FIX_MADEXCEPT if you are using crash on buffer overrun/underrun feature from MadExcept }\n{.$DEFINE FIX_MADEXCEPT}\n{.$define DEVMODE}\n\n{$IFDEF FPC}\n{$MODE DELPHI}\n{$HINTS OFF}\n{$WARN 4045 OFF}\n{$WARN 4055 OFF}\n{$WARN 4056 OFF}\n{$WARN 4082 OFF}\n{$WARN 5024 OFF}\n{$WARN 5028 OFF}\n{$WARN 5057 OFF}\n{$WARN 5058 OFF}\n{$ENDIF FPC}\n\ninterface\n\n{$I DDetoursDefs.inc}\n\nuses\n\n{$IFDEF RENAMED_NAMESPACE}\n  System.SysUtils,\n  System.Classes,\n  WinApi.Windows,\n  WinApi.TLHelp32,\n{$IFNDEF SUPPORTS_MONITOR}\n  System.SyncObjs,\n{$ENDIF SUPPORTS_MONITOR}\n{$ELSE !RENAMED_NAMESPACE}\n  SysUtils,\n  Windows,\n  Classes,\n{$IFNDEF SUPPORTS_MONITOR}\n  SyncObjs,\n{$ENDIF SUPPORTS_MONITOR}\n{$IFNDEF FPC}\n  TLHelp32,\n{$ENDIF FPC}\n{$ENDIF RENAMED_NAMESPACE}\n{$IFDEF SUPPORTS_RTTI}\n  System.Generics.Collections,\n  System.Typinfo, System.RTTI,\n{$ENDIF SUPPORTS_RTTI}\n  LegacyTypes,\n  CPUID,\n  InstDecode;\n\ntype\n  InterceptException = Exception;\n  TTransactionOption = (toSuspendThread);\n  TTransactionOptions = set of TTransactionOption;\n\n  TInterceptOption = (ioForceLoad, ioRecursive);\n  TInterceptOptions = set of TInterceptOption;\n\nconst\n  { Maximum allowed number of hooks. }\n  MAX_HOOKS = 7;\n\n  DefaultInterceptOptions = [];\n  SErrorInvalidTType = '<T> must be a method';\n\n  { ========================================= DDetours Interface ========================================= }\nfunction InterceptCreate(const TargetProc, InterceptProc: Pointer; const Param: Pointer = nil; const Options: TInterceptOptions = DefaultInterceptOptions)\n  : Pointer; overload;\nfunction InterceptCreate(const TargetInterface; MethodIndex: Integer; const InterceptProc: Pointer; const Param: Pointer = nil;\n  const Options: TInterceptOptions = DefaultInterceptOptions): Pointer; overload;\nfunction InterceptCreate(const Module, MethodName: String; const InterceptProc: Pointer; const Param: Pointer = nil;\n  const Options: TInterceptOptions = DefaultInterceptOptions): Pointer; overload;\nprocedure InterceptCreate(const TargetProc, InterceptProc: Pointer; var TrampoLine: Pointer; const Param: Pointer = nil;\n  const Options: TInterceptOptions = DefaultInterceptOptions); overload;\n\n{$IFDEF SUPPORTS_RTTI}\nfunction InterceptCreate(const TargetInterface; const MethodName: String; const InterceptProc: Pointer; const Param: Pointer = nil;\n  const Options: TInterceptOptions = DefaultInterceptOptions): Pointer; overload;\n{$ENDIF SUPPORTS_RTTI}\nfunction InterceptRemove(const TrampoLine: Pointer): Integer; overload;\n\nfunction GetHookCount(const TargetProc: Pointer): Integer; overload;\nfunction GetHookCount(const TargetInterface; MethodIndex: Integer): Integer; overload;\n{$IFDEF SUPPORTS_RTTI}\nfunction GetHookCount(const TargetInterface; const MethodName: String): Integer; overload;\n{$ENDIF SUPPORTS_RTTI}\nfunction IsHooked(const TargetProc: Pointer): Boolean; overload;\nfunction IsHooked(const TargetInterface; MethodIndex: Integer): Boolean; overload;\n{$IFDEF SUPPORTS_RTTI}\nfunction IsHooked(const TargetInterface; const MethodName: String): Boolean; overload;\n{$ENDIF SUPPORTS_RTTI}\nfunction PatchVt(const TargetInterface; MethodIndex: Integer; InterceptProc: Pointer): Pointer;\nfunction UnPatchVt(const TrampoLine: Pointer): Boolean;\n\nfunction BeginTransaction(Options: TTransactionOptions = [toSuspendThread]): THandle;\nfunction EndTransaction(Handle: THandle): Boolean;\n\nfunction EnterRecursiveSection(var TrampoLine; MaxRecursionLevel: NativeInt = 0): Boolean;\nfunction ExitRecursiveSection(var TrampoLine): Boolean;\n\nfunction GetCreatorThreadIdFromTrampoline(var TrampoLine): TThreadId;\nfunction GetTrampolineParam(var TrampoLine): Pointer;\n\n{$IFDEF SUPPORTS_GENERICS}\n\ntype\n  IIntercept<T, U> = interface(IInterface)\n    ['{EECBF3C2-3938-4923-835A-B0A6AD27744D}']\n    function GetTrampoline(): T;\n    function GetParam(): U;\n    function GetCreatorThreadId(): TThreadId;\n    function GetInterceptOptions(): TInterceptOptions;\n    function EnterRecursive(MaxRecursionLevel: NativeInt = 0): Boolean;\n    function ExitRecursive(): Boolean;\n\n    property NextHook: T read GetTrampoline;\n    property TrampoLine: T read GetTrampoline; // alias to NextHook\n    property Param: U read GetParam;\n    property CreatorThreadId: TThreadId read GetCreatorThreadId;\n    property InterceptOptions: TInterceptOptions read GetInterceptOptions;\n  end;\n\n  {\n    Based on David Millington's original implementation TDetours<T>.\n  }\n  TIntercept<T, U> = class(TInterfacedObject, IIntercept<T, U>)\n  private\n    FNextHook: T;\n    FTrampolinePtr: Pointer;\n    FParam: U;\n    FCreatorThreadId: TThreadId;\n    FInterceptOptions: TInterceptOptions;\n    function TToPointer(const A): Pointer;\n    function PointerToT(const P): T;\n    function EnsureTIsMethod(): Boolean;\n  public\n    function GetTrampoline(): T;\n    function GetParam(): U;\n    function GetCreatorThreadId(): TThreadId;\n    function GetInterceptOptions(): TInterceptOptions;\n    function EnterRecursive(MaxRecursionLevel: NativeInt = 0): Boolean;\n    function ExitRecursive(): Boolean;\n    constructor Create(const TargetProc, InterceptProc: T; const AParam: U; const AInterceptOptions: TInterceptOptions = DefaultInterceptOptions); virtual;\n    destructor Destroy(); override;\n    property Param: U read FParam;\n    property NextHook: T read FNextHook;\n    property TrampoLine: T read FNextHook; // alias to NextHook\n    property CreatorThreadId: TThreadId read FCreatorThreadId;\n    property InterceptOptions: TInterceptOptions read FInterceptOptions;\n  end;\n\n  TIntercept<T> = class(TIntercept<T, Pointer>)\n  public\n    constructor Create(const TargetProc, InterceptProc: T; const AParam: Pointer = nil;\n      const AInterceptOptions: TInterceptOptions = DefaultInterceptOptions); override;\n  end;\n{$ENDIF SUPPORTS_GENERICS}\n\ntype\n  DetourException = Exception;\n\nimplementation\n\nconst\n  { Nops }\n  Nop9: array [0 .. 8] of Byte = ($66, $0F, $1F, $84, $00, $00, $00, $00, $00);\n  Nop8: array [0 .. 7] of Byte = ($0F, $1F, $84, $00, $00, $00, $00, $00);\n  Nop7: array [0 .. 6] of Byte = ($0F, $1F, $80, $00, $00, $00, $00);\n  Nop6: array [0 .. 5] of Byte = ($66, $0F, $1F, $44, $00, $00);\n  Nop5: array [0 .. 4] of Byte = ($0F, $1F, $44, $00, $00);\n  Nop4: array [0 .. 3] of Byte = ($0F, $1F, $40, $00);\n  Nop3: array [0 .. 2] of Byte = ($0F, $1F, $00);\n  Nop2: array [0 .. 1] of Byte = ($66, $90);\n  Nop1: array [0 .. 0] of Byte = ($90);\n  MultiNops: array [0 .. 8] of PByte = ( //\n    @Nop1, { Standard Nop }\n    @Nop2, { 2 Bytes Nop }\n    @Nop3, { 3 Bytes Nop }\n    @Nop4, { 4 Bytes Nop }\n    @Nop5, { 5 Bytes Nop }\n    @Nop6, { 6 Bytes Nop }\n    @Nop7, { 7 Bytes Nop }\n    @Nop8, { 8 Bytes Nop }\n    @Nop9 { 9 Bytes Nop }\n    );\n\n  { Arithmetic operands }\n  arNone = $00;\n  arPlus = $08;\n  arMin = $10;\n  arAdd = arPlus or $01;\n  arSub = arMin or $01;\n  arInc = arPlus or $02;\n  arDec = arMin or $02;\n\n  { Instructions OpCodes }\n  opJmpRelz = $E9;\n  opJmpRelb = $EB;\n  opJmpMem = $25FF;\n  opTestb = $85;\n  opPrfOpSize = $66;\n  opPrfAddrSize = $67;\n  opNop = $90;\n\n  { thread constants }\n  THREAD_SUSPEND_RESUME = $0002;\n\n  { Error messages }\n  SErrorSmallFunctionSize = 'Size of function is too small, risk to override others adjacent functions.';\n  SErrorInvalidJmp = 'Invalid JMP Type.';\n  SErrorInvalidJmp64 = 'Invalid JMP Type for x64.';\n  SErrorInvalidJmp32 = 'Invalid JMP Type for x32.';\n  SErrorInvalidDstSave = 'Invalid DstSave Address pointer.';\n  SErrorUnsupportedMultiNop = 'Multi Bytes Nop Instructions not supported by your CPU.';\n  SErrorRipDisp = 'Failed to correcr RIP Displacement.';\n  SErrorBigTrampoSize = 'Exceed maximum TrampoSize.';\n  SErrorMaxHook = 'Exceed maximum allowed of hooks.';\n  SErrorInvalidTargetProc = 'Invalid TargetProc Pointer.';\n  SErrorInvalidInterceptProc = 'Invalid InterceptProc Pointer.';\n  SErrorInvalidDescriptor = 'Invalid Descriptor.';\n  SErrorInvalidTrampoline = 'Invalid TrampoLine Pointer.';\n  SErrorBeginUnHook = 'BeginUnHooks must be called outside BeginHooks/EndHooks.';\n  SErrorRecursiveSectionUnsupported = 'Trampoline was not marked to use recursive section.';\n  SErrorTlsOutOfIndexes = 'Tls out of indexes.';\n  { JMP Type }\n  JT_NONE = 0;\n  JT_REL8 = 1;\n  JT_REL16 = 2;\n  JT_REL32 = 3;\n  JT_MEM16 = 4;\n  JT_MEM32 = 5;\n  JT_MEM64 = 6;\n  JT_RIPZ = 7;\n\n{$IFDEF CPUX64}\n  JT_MEMN = JT_MEM64;\n{$ELSE !CPUX64}\n  JT_MEMN = JT_MEM32;\n{$ENDIF CPUX64}\n  { Jmp Type To Size }\n  JmpTypeToSize: array [0 .. 7] of Byte = ( //\n    0, { None }\n    2, { JT_REL8  = $EB + Rel8 }\n    4, { JT_REL16 = OpSizePrf + $E9 + Rel16 }\n    5, { JT_REL32 = $E9 + Rel32 }\n    7, { JT_MEM16 = OpSizePrf + $FF /4 + Disp32 }\n    6, { JT_MEM32 = $FF /4 + Disp32 }\n    6, { JT_MEM64 = $FF /4 + Disp32 }\n    14 { JT_RIPZ  = $FF /4 + Disp32 + DQ }\n    );\n\n  SizeToJmpType: array [0 .. 4] of Byte = ( //\n{$IFDEF CPUX86}\n    JT_REL8, { db }\n    JT_REL16, { dw }\n    JT_REL32, { dd }\n    JT_MEM32, { dd }\n    JT_MEM32 { dd }\n{$ELSE !CPUX86}\n    JT_REL8, { db }\n    JT_REL32, { dw }\n    JT_REL32, { dd }\n    JT_MEM64, { dq }\n    JT_MEM64 { dq }\n{$ENDIF CPUX86}\n    );\n\n  DscrSigSize = $08;\n  TmpSize = 32;\n\n  TrampolineSignature = $544C544C;\n\ntype\n  TArrayOfThreadId = array [0 .. HIGH(SmallInt) - 1] of DWORD;\n  PArrayOfThreadId = ^TArrayOfThreadId;\n\n  TTransactionStruct = record\n    Options: TTransactionOptions;\n    TID: DWORD;\n    PID: DWORD;\n    ThreadPriority: Integer;\n    SuspendedThreadCount: Integer;\n    SuspendedThreads: PArrayOfThreadId;\n  end;\n\n  PTransactionStruct = ^TTransactionStruct;\n\n  TOpenThread = function(dwDesiredAccess: DWORD; bInheritHandle: BOOL; dwThreadId: DWORD): THandle; stdcall;\n\n  TDscrSig = array [0 .. DscrSigSize - 1] of Byte;\n\n  TVirtualProtect = function(lpAddress: Pointer; dwSize: SIZE_T; flNewProtect: DWORD; var OldProtect: DWORD): BOOL; stdcall;\n  TVirtualAlloc = function(lpvAddress: Pointer; dwSize: SIZE_T; flAllocationType, flProtect: DWORD): Pointer; stdcall;\n  TVirtualQuery = function(lpAddress: Pointer; var lpBuffer: TMemoryBasicInformation; dwLength: SIZE_T): SIZE_T; stdcall;\n  TFlushInstructionCache = function(hProcess: THandle; const lpBaseAddress: Pointer; dwSize: SIZE_T): BOOL; stdcall;\n  TGetCurrentProcess = function: THandle; stdcall;\n  TVirtualFree = function(lpAddress: Pointer; dwSize: SIZE_T; dwFreeType: DWORD): BOOL; stdcall;\n\n  { TEnumThreadCallBack for EnumProcessThreads }\n  TEnumThreadCallBack = function(ID: DWORD; Param: Pointer): Boolean;\n\n  TInternalFuncs = record\n    VirtualAlloc: TVirtualAlloc;\n    VirtualFree: TVirtualFree;\n    VirtualProtect: TVirtualProtect;\n    VirtualQuery: TVirtualQuery;\n    FlushInstructionCache: TFlushInstructionCache;\n    GetCurrentProcess: TGetCurrentProcess;\n  end;\n\n  TTrampoInfo = record\n    Addr: PByte; // Pointer to first trampoline instruction .\n    Size: Byte; // Stolen bytes size .\n    PData: PByte; // Original Stolen bytes.\n  end;\n\n  PTrampoInfo = ^TTrampoInfo;\n\n  TJmpMem = packed record\n    OpCode: WORD; // $0F$25\n    Disp32: Integer;\n  end;\n\n  PJmpMem = ^TJmpMem;\n\n  TDescriptor = packed record\n    Sig: TDscrSig; { Table signature. }\n    DscrAddr: PByte; { Pointer that hold jmp address (if Used)! }\n    nHook: Byte; { Number of hooks . }\n    Flags: Byte; { Reserved for future use! }\n    ExMem: PByte; { Reserved for jmp (if used) & for Trampoline ! }\n    OrgPtr: PByte; { Original Target Proc address. }\n    Trampo: PTrampoInfo; { Pointer to TrampoInfo struct. }\n    { Array that hold jmp destination address. }\n    JmpAddrs: array [0 .. MAX_HOOKS] of PByte;\n    {\n      Mark the beginning of descriptor code executing .\n      ==> Must be NOP .\n    }\n    CodeEntry: Byte;\n    { Jmp Instruction for NextHook call and Trampoline call ! }\n    JmpMems: array [0 .. MAX_HOOKS] of TJmpMem;\n  end;\n\n  PDescriptor = ^TDescriptor;\n\n  TNextHook = packed record\n    ID: Byte; { Hook ID . }\n    PDscr: PDescriptor;\n    Signature: Cardinal;\n    threadid: TThreadId;\n    Param: Pointer;\n    TlsRecursionLevelIndex: DWORD;\n    InterceptOptions: TInterceptOptions;\n  end;\n\n  PNextHook = ^TNextHook;\n\n  TTrampoDataVt = record\n    vAddr: Pointer;\n    Addr: Pointer;\n  end;\n\n  PTrampoDataVt = ^TTrampoDataVt;\n\nconst\n  TrampoSize = SizeOf(TNextHook) + 64;\n\n  { Descriptor Signature }\n{$IFDEF CPUX64}\n  DscrSig: TDscrSig = ( //\n    $90, { NOP }\n    $40, { REX }\n    $40, { REX }\n    $40, { REX }\n    $0F, { ESCAPE TWO BYTE }\n    $1F, { HINT_NOP }\n    $F3, { PRF }\n    $F3 { PRF }\n    );\n{$ELSE !CPUX64}\n  DscrSig: TDscrSig = ( //\n    $90, { NOP }\n    $40, { INC EAX }\n    $48, { DEC EAX }\n    $90, { NOP }\n    $0F, { ESCAPE TWO BYTE }\n    $1F, { HINT_NOP }\n    $F3, { PRF }\n    $F3 { PRF }\n    );\n{$ENDIF CPUX64}\n{$IFDEF FPC}\n{$I 'TlHelp32.inc'}\n{$ENDIF FPC}\n\nvar\n  OpenThread: TOpenThread = nil;\n{$IFDEF FPC}\n  CreateToolhelp32Snapshot: TCreateToolhelp32Snapshot = nil;\n  Thread32First: TThread32First = nil;\n  Thread32Next: TThread32Next = nil;\n{$ENDIF FPC}\n  hKernel: THandle;\n  OpenThreadExist: Boolean = False;\n  FreeKernel: Boolean = False;\n  SizeOfAlloc: DWORD = 0; // See initialization !\n  SysInfo: TSystemInfo;\n  InternalFuncs: TInternalFuncs;\n{$IFDEF SUPPORTS_MONITOR}\n  FLock: TObject = nil;\n{$ELSE !SUPPORTS_MONITOR}\n  FLock: TCriticalSection = nil;\n{$ENDIF SUPPORTS_MONITOR }\n  { ================================== Utils ================================== }\n\nfunction GetUInt64Size(const Value: UInt64): Integer; {$IFDEF SUPPORTS_INLINE}inline; {$ENDIF SUPPORTS_INLINE}\nbegin\n  if UInt8(Value) = Value then\n    Result := 1\n  else if UInt16(Value) = Value then\n    Result := 2\n  else if UInt32(Value) = Value then\n    Result := 4\n  else\n    Result := 8;\nend;\n\nfunction GetInt64Size(const Value: Int64): Integer; {$IFDEF SUPPORTS_INLINE}inline; {$ENDIF SUPPORTS_INLINE}\nbegin\n  if Int8(Value) = Value then\n    Result := 1\n  else if Int16(Value) = Value then\n    Result := 2\n  else if Int32(Value) = Value then\n    Result := 4\n  else\n    Result := 8;\nend;\n\nprocedure EnterLook(LockedObject: TObject); {$IFDEF SUPPORTS_INLINE}inline; {$ENDIF SUPPORTS_INLINE}\nbegin\n{$IFDEF SUPPORTS_MONITOR}\n  TMonitor.Enter(LockedObject);\n{$ELSE !SUPPORTS_MONITOR}\n  TCriticalSection(LockedObject).Enter();\n{$ENDIF SUPPORTS_MONITOR}\nend;\n\nprocedure LeaveLook(LockedObject: TObject); {$IFDEF SUPPORTS_INLINE}inline; {$ENDIF SUPPORTS_INLINE}\nbegin\n{$IFDEF SUPPORTS_MONITOR}\n  TMonitor.Exit(LockedObject);\n{$ELSE !SUPPORTS_MONITOR}\n  TCriticalSection(LockedObject).Leave();\n{$ENDIF SUPPORTS_MONITOR}\nend;\n\nfunction EnumProcessThreads(PID: DWORD; CallBack: TEnumThreadCallBack; Param: Pointer): BOOL;\nvar\n  hSnap: THandle;\n  te: TThreadEntry32;\n  Next: Boolean;\nbegin\n  hSnap := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, PID);\n  Result := hSnap <> INVALID_HANDLE_VALUE;\n  if Result then\n  begin\n    te.dwSize := SizeOf(TThreadEntry32);\n    Next := Thread32First(hSnap, te);\n    while Next do\n    begin\n      if (te.th32OwnerProcessID = PID) then\n      begin\n        try\n          if not CallBack(te.th32ThreadID, Param) then\n            break;\n        except\n        end;\n      end;\n      Next := Thread32Next(hSnap, te);\n    end;\n    Result := CloseHandle(hSnap);\n  end;\nend;\n\nfunction SetMemPermission(const P: Pointer; const Size: SIZE_T; const NewProtect: DWORD): DWORD;\nconst\n  PAGE_EXECUTE_FLAGS = PAGE_EXECUTE or PAGE_EXECUTE_READ or PAGE_EXECUTE_READWRITE or PAGE_EXECUTE_WRITECOPY;\nbegin\n  Result := 0;\n  if Assigned(P) and (Size > 0) and (NewProtect > 0) then\n  begin\n    if InternalFuncs.VirtualProtect(P, Size, NewProtect, Result) then\n      if (NewProtect and PAGE_EXECUTE_FLAGS <> 0) then\n        {\n          If the protected region will be executed\n          => We need to update the cpu cache !\n        }\n        InternalFuncs.FlushInstructionCache(InternalFuncs.GetCurrentProcess(), P, Size);\n  end;\nend;\n\nfunction GetDispDataSize(PInst: PInstruction): Integer;\nbegin\n  Result := 0;\n  if PInst^.Disp.Flags and dfUsed <> 0 then\n  begin\n    if PInst^.Archi = CPUX32 then\n    begin\n      if PInst^.Prefixes and Prf_OpSize <> 0 then\n        Result := ops16bits\n      else\n        Result := ops32bits;\n      Exit;\n    end\n    else\n    begin\n      case PInst^.OperandFlags of\n        opdD64:\n          begin\n            {\n              Defaults to O64 in PM64.\n              PrfOpSize results in O16.\n            }\n            if PInst^.Prefixes and Prf_OpSize <> 0 then\n              Result := ops16bits\n            else\n              Result := ops64bits;\n          end;\n        opdF64, opdDv64:\n          begin\n            { The operand size is forced to a 64-bit operand size in PM64 ! }\n            Result := (ops64bits);\n            Exit;\n          end;\n        opdDf64:\n          begin\n            {\n              Defaults to O64 in PM64.\n              PrfOpSize results in O16 in AMD64.\n              PrfOpSize is ignored in EM64T.\n            }\n            if (CPUVendor = vAMD) and (PInst^.Prefixes and Prf_OpSize <> 0) then\n              Result := (ops16bits)\n            else\n              Result := (ops64bits);\n            Exit;\n          end;\n      else\n        begin\n          if PInst^.Rex.W then\n            Result := (ops64bits)\n          else if (PInst^.Prefixes and Prf_OpSize <> 0) then\n            Result := (ops16bits)\n          else\n            Result := (ops32bits);\n          Exit;\n        end;\n      end;\n    end;\n  end;\nend;\n\nfunction fDecodeInst(PInst: PInstruction): Integer;\nvar\n  IsNxtInstData: Boolean;\nbegin\n  { Include VEX decoding if the cpu support it! }\n  if (VEX in CPUEncoding) then\n    PInst.Options := DecodeVex;\n\n  Result := DecodeInst(PInst);\n\n{$IFDEF CPUX64}\n  IsNxtInstData := ((PInst^.Disp.Flags and (dfUsed or dfRip) = (dfUsed or dfRip)) and (PInst^.Disp.Value = 0));\n{$ELSE !CPUX64}\n  IsNxtInstData := (PInst^.Disp.Value = Int64(PInst^.NextInst));\n{$ENDIF CPUX64}\n  if IsNxtInstData then\n  begin\n    {\n      Check if the Next Instruction is data !\n      If so , That's mean it's not a valid instruction .\n      We must skip this data ..\n      otherwise , disassembling next instructions will fail !\n    }\n    Inc(Result, GetDispDataSize(PInst));\n    PInst^.InstSize := Result;\n  end;\nend;\n\nfunction RoundMultipleOf(const Value, MultipleOf: NativeInt): NativeInt; {$IFDEF SUPPORTS_INLINE}inline; {$ENDIF SUPPORTS_INLINE}\nbegin\n  if Value = 0 then\n  begin\n    Result := (MultipleOf);\n    Exit;\n  end;\n  Result := ((Value + (MultipleOf - 1)) and not(MultipleOf - 1));\nend;\n\nfunction AllocMemAt(const Addr: Pointer; const MemSize, flProtect: DWORD): Pointer;\nvar\n  mbi: TMemoryBasicInformation;\n  SysInfo: TSystemInfo;\n  pBase: PByte;\n  P: PByte;\n  Q: PByte;\n  pMax, pMin: PByte;\n  dwAllocGran: DWORD;\nbegin\n  { Alloc memory on the specific nearest address from the Addr . }\n\n  Result := nil;\n  P := PByte(Addr);\n  if not Assigned(P) then\n  begin\n    Result := InternalFuncs.VirtualAlloc(nil, MemSize, MEM_RESERVE or MEM_COMMIT, flProtect);\n    Exit;\n  end;\n\n  GetSystemInfo(SysInfo);\n  pMin := SysInfo.lpMinimumApplicationAddress;\n  pMax := SysInfo.lpMaximumApplicationAddress;\n  dwAllocGran := SysInfo.dwAllocationGranularity;\n\n  if (NativeUInt(P) < NativeUInt(pMin)) or (NativeUInt(P) > NativeUInt(pMax)) then\n    Exit;\n  if InternalFuncs.VirtualQuery(P, mbi, SizeOf(mbi)) = 0 then\n    Exit;\n\n  pBase := mbi.BaseAddress;\n  Q := pBase;\n  while NativeUInt(Q) < NativeUInt(pMax) do\n  begin\n    if InternalFuncs.VirtualQuery(Q, mbi, SizeOf(mbi)) = 0 then\n      Exit;\n    if (mbi.State = MEM_FREE) and (mbi.RegionSize >= dwAllocGran) and (mbi.RegionSize >= MemSize) then\n    begin\n      { The address (P) must be multiple of the allocation granularity (dwAllocationGranularity) . }\n      P := PByte(RoundMultipleOf(NativeInt(Q), dwAllocGran));\n      Result := InternalFuncs.VirtualAlloc(P, MemSize, MEM_RESERVE or MEM_COMMIT, flProtect);\n      if Assigned(Result) then\n        Exit;\n    end;\n    Inc(Q, mbi.RegionSize); // Next Region .\n  end;\n  {\n    If thre is no memory available in the range [Addr - pMax]\n    try to allocate at the range [pMin - Addr]\n  }\n  Q := pBase;\n  while NativeUInt(Q) > NativeUInt(pMin) do\n  begin\n    if InternalFuncs.VirtualQuery(Q, mbi, SizeOf(mbi)) = 0 then\n      Exit;\n    if (mbi.State = MEM_FREE) and (mbi.RegionSize >= dwAllocGran) and (mbi.RegionSize >= MemSize) then\n    begin\n      P := PByte(RoundMultipleOf(NativeInt(Q), dwAllocGran));\n      Result := InternalFuncs.VirtualAlloc(P, MemSize, MEM_RESERVE or MEM_COMMIT, flProtect);\n      if Assigned(Result) then\n        Exit;\n    end;\n    Dec(Q, mbi.RegionSize); // Previous Region.\n  end;\nend;\n\nfunction TryAllocMemAt(const Addr: Pointer; const MemSize, flProtect: DWORD): Pointer;\nvar\n  MEM_64: DWORD;\nbegin\n  MEM_64 := 0;\n  Result := AllocMemAt(Addr, MemSize, flProtect);\n  if not Assigned(Result) then\n  begin\n{$IFDEF CPUX64}\n    { Allocates memory at the highest possible address }\n    if (UInt64(Addr) and $FFFFFFFF00000000 <> 0) then\n      MEM_64 := MEM_TOP_DOWN;\n{$ENDIF CPUX64}\n    Result := InternalFuncs.VirtualAlloc(nil, MemSize, MEM_RESERVE or MEM_COMMIT or MEM_64, flProtect);\n  end;\nend;\n\nfunction InsertJmp(Src, Dst: PByte; JmpType: Integer; const DstSave: PByte = nil): Integer;\nvar\n  Offset: NativeInt;\n  JmpSize: Integer;\nbegin\n  Result := 1;\n  JmpSize := JmpTypeToSize[JmpType];\n  Offset := NativeInt(NativeInt(Dst) - NativeInt(Src)) - JmpSize;\n  case JmpType of\n    JT_NONE:\n      begin\n        raise InterceptException.Create(SErrorInvalidJmp);\n      end;\n    JT_REL8:\n      begin\n        PByte(Src)^ := opJmpRelb;\n        Inc(Src);\n        PInt8(Src)^ := Int8(Offset);\n      end;\n    JT_REL16:\n      begin\n{$IFDEF CPUX64}\n        {\n          JMP Rel16\n          ==> Not supported on x64!\n        }\n        raise InterceptException.Create(SErrorInvalidJmp64);\n{$ENDIF CPUX64}\n        PByte(Src)^ := opPrfOpSize;\n        Inc(Src);\n        PByte(Src)^ := opJmpRelz;\n        Inc(Src);\n        PInt16(Src)^ := Int16(Offset);\n      end;\n    JT_REL32:\n      begin\n        PByte(Src)^ := opJmpRelz;\n        Inc(Src);\n        PInt32(Src)^ := Offset;\n      end;\n    JT_MEM16:\n      begin\n{$IFDEF CPUX64}\n        {\n          JMP WORD [012345]\n          ==> Not supported on x64!\n        }\n        raise InterceptException.Create(SErrorInvalidJmp64);\n{$ENDIF CPUX64}\n        if not Assigned(DstSave) then\n          raise InterceptException.Create(SErrorInvalidDstSave);\n        PByte(Src)^ := opPrfOpSize;\n        Inc(Src);\n        PWord(Src)^ := opJmpMem;\n        Inc(Src, 2);\n        PUInt32(Src)^ := UInt32(DstSave);\n        PUInt16(DstSave)^ := UInt16(Dst);\n      end;\n    JT_MEM32:\n      begin\n{$IFDEF CPUX64}\n        {\n          JMP DWORD [012345]\n          ==> Not supported on x64!\n        }\n        raise InterceptException.Create(SErrorInvalidJmp64);\n{$ENDIF CPUX64}\n        if not Assigned(DstSave) then\n          raise InterceptException.Create(SErrorInvalidDstSave);\n        PWord(Src)^ := opJmpMem;\n        Inc(Src, 2);\n        PUInt32(Src)^ := UInt32(DstSave);\n        PUInt32(DstSave)^ := UInt32(Dst);\n      end;\n    JT_MEM64:\n      begin\n{$IFDEF CPUX86}\n        {\n          JMP QWORD [0123456789]\n          ==> Not supported on x32!\n        }\n        raise InterceptException.Create(SErrorInvalidJmp32);\n{$ENDIF CPUX86}\n        if not Assigned(DstSave) then\n          raise InterceptException.Create(SErrorInvalidDstSave);\n        { RIP Disp ! }\n        PUInt64(DstSave)^ := UInt64(Dst);\n        Offset := NativeInt(NativeInt(DstSave) - NativeInt(Src)) - JmpSize;\n\n        PWord(Src)^ := opJmpMem;\n        Inc(Src, 2);\n        PInt32(Src)^ := Offset;\n      end;\n    JT_RIPZ:\n      begin\n{$IFDEF CPUX86}\n        raise InterceptException.Create(SErrorInvalidJmp32);\n{$ENDIF CPUX86}\n        {\n          This is the most harder way to insert a jump !\n          Why ?\n          because we are going to mix code & data !\n          Thats mean when disassembling instructions after\n          this branch .. you will have a corrupted dissambled\n          structure !\n\n          The only way to detect this kind of jmp is:\n          to use fDecodeInst rather than DecodeInst routine .\n\n          ==> We should avoid using this kind of jmp\n          in the original target proc .\n\n          ==> It's Ok to use in others situation .\n        }\n\n        PWord(Src)^ := opJmpMem;\n        Inc(Src, 2);\n        PInt32(Src)^ := $00;\n        Inc(Src, 4);\n        PUInt64(Src)^ := UInt64(Dst);\n      end;\n  end;\nend;\n\nfunction GetJmpType(Src, Dst, DstSave: PByte): Integer;\nvar\n  Offset: NativeInt;\n  OffsetSize: Integer;\nbegin\n  Offset := NativeInt(NativeInt(Src) - NativeInt(Dst));\n  OffsetSize := GetInt64Size(Offset);\n  Result := SizeToJmpType[OffsetSize shr 1];\n{$IFDEF CPUX64}\n  if Result = JT_MEM64 then\n  begin\n    if not Assigned(DstSave) then\n      raise InterceptException.Create(SErrorInvalidDstSave);\n    Offset := NativeInt(NativeInt(DstSave) - NativeInt(Src)) - 7;\n    if Integer(Offset) <> Offset then\n    begin\n      Result := (JT_RIPZ);\n      Exit;\n    end;\n  end;\n{$ENDIF CPUX64}\nend;\n\nfunction IsMultiBytesNop(P: Pointer; Size: Integer): Boolean;\nvar\n  i: Integer;\nbegin\n  Result := False;\n  if Size > 0 then\n  begin\n    while (Size > 0) do\n    begin\n      for i := Length(MultiNops) downto 1 do\n      begin\n        if Size >= i then\n        begin\n          Result := CompareMem(MultiNops[i - 1], P, i);\n          if Result then\n          begin\n            Inc(PByte(P), i);\n            Dec(Size, i);\n            break;\n          end;\n        end;\n      end;\n      if not Result then\n        Exit;\n    end;\n    Result := True;\n  end;\nend;\n\nprocedure FillMultiNop(var Buffer; Size: Integer);\nvar\n  i: Integer;\n  P: PByte;\nbegin\n  { Multi Bytes Nop Instruction is fast to execute compared to\n    the traditional NOP instruction.\n\n    However it's not supported by all CPU !\n    ==> Use FillNop(P,Size,True).\n\n    ==> CPUID implements a routine to detect\n    if the CPU supports Multi Bytes Nop .\n  }\n  if not(iMultiNop in CPUInsts) then\n    raise InterceptException.Create(SErrorUnsupportedMultiNop);\n\n  P := PByte(@Buffer);\n  for i := Length(MultiNops) downto 1 do\n  begin\n    while Size >= i do\n    begin\n      Move(MultiNops[i - 1]^, P^, i);\n      Dec(Size, i);\n      Inc(P, i);\n    end;\n    if Size = 0 then\n      Exit;\n  end;\nend;\n\nfunction IsNop(P: PByte; Size: Integer): Boolean;\nvar\n  i: Integer;\nbegin\n  { Return True if the first instructions are nop/multi nop. }\n  Result := False;\n  if iMultiNop in CPUInsts then\n    Result := IsMultiBytesNop(P, Size)\n  else\n    for i := 0 to Size - 1 do\n    begin\n      Result := (P^ = opNop);\n      if not Result then\n        Exit;\n      Inc(P); // Next Byte.\n    end;\nend;\n\nprocedure FillNop(var P; Size: Integer; MultipleNop: Boolean);\nbegin\n  if MultipleNop and (iMultiNop in CPUInsts) then\n    FillMultiNop(P, Size)\n  else\n    FillChar(P, Size, opNop);\nend;\n\nfunction GetPrefixesCount(Prefixes: WORD): Byte;\nvar\n  Prf: WORD;\n  i: Byte;\nbegin\n  { Get prefixes count used by the instruction. }\n  Result := 0;\n  if Prefixes = 0 then\n    Exit;\n\n  Prf := 0;\n  i := 0;\n  Prefixes := Prefixes and not Prf_VEX;\n  while Prf < $8000 do\n  begin\n    Prf := (1 shl i);\n    if (Prf and Prefixes = Prf) then\n      Inc(Result);\n    Inc(i);\n  end;\nend;\n\nfunction GetInstOpCodes(PInst: PInstruction; P: PByte): ShortInt;\nvar\n  nPrfs: Byte;\nbegin\n  {\n    Return opcodes length\n    Instruction OpCodes in arg P  .\n  }\n  Result := 0;\n  FillChar(P^, MAX_INST_LENGTH_N, $90);\n  nPrfs := GetPrefixesCount(PInst^.Prefixes);\n  Inc(Result, nPrfs);\n  case PInst^.OpTable of\n    tbTwoByte:\n      if PInst^.Prefixes and Prf_VEX3 = 0 then\n        Inc(Result); // $0F\n    tbThreeByte:\n      begin\n        if PInst^.Prefixes and Prf_VEX3 = 0 then\n          Inc(Result, 2); // 0F + 38|3A !\n      end;\n    tbFPU:\n      Inc(Result, 2); // [$D8..$D9] + ModRm !\n  end;\n  if PInst^.Prefixes and Prf_Vex2 <> 0 then\n    Inc(Result); // VEX.P0\n  if PInst^.Prefixes and Prf_VEX3 <> 0 then\n    Inc(Result, 2); // VEX.P0 + VEX.P1\n  if PInst^.OpKind = kGrp then\n    Inc(Result, 2) // Group + ModRm\n  else\n    Inc(Result); // OpCode\n  if Assigned(P) then\n    Move(PInst^.Addr^, P^, Result);\nend;\n\nfunction GetJccOpCode(PInst: PInstruction; RelSize: Integer): DWORD;\nvar\n  OpCode: Byte;\n  Opcodes: array [0 .. 3] of Byte;\nbegin\n  FillChar(PByte(@Opcodes[0])^, 4, #00);\n  OpCode := PInst^.OpCode and $F;\n  case RelSize of\n    ops8bits:\n      begin\n        Opcodes[0] := $70 or OpCode;\n      end;\n    ops16bits:\n      begin\n        Opcodes[0] := opPrfOpSize;\n        Opcodes[1] := $0F;\n        Opcodes[2] := $80 or OpCode;\n      end;\n    ops32bits:\n      begin\n        Opcodes[0] := $0F;\n        Opcodes[1] := $80 or OpCode;\n      end;\n  end;\n  Result := PDWORD(@Opcodes[0])^;\nend;\n\nfunction CorrectJ(PInst: PInstruction; NewAddr: PByte): Integer;\nconst\n  { Convert LOOP instruction to relative word jcc ! }\n  LOOP_To_JccZ: array [0 .. 3] of WORD = ($850F, $840F, $840F, $9090);\n  { Convert LOOP instruction to relative byte jcc ! }\n  LOOP_To_JccB: array [0 .. 3] of Byte = ($75, $74, $75, $90);\nvar\n  Offset: Int64;\n  POpc: PByte;\n  NOpc: DWORD;\n  PQ: PByte;\n  Relsz: Integer;\n  JmpType: Integer;\n  JmpSize: Integer;\nbegin\n  PQ := NewAddr;\n  JmpSize := 0;\n  GetMem(POpc, MAX_INST_LENGTH_N + 1);\n  try\n    // Opcsz := GetInstOpCodes(PInst, POpc);\n    Offset := Int64(Int64(PInst^.Branch.Target) - Int64(PQ) - 6);\n    Relsz := GetInt64Size(Offset);\n{$IFDEF CPUX64}\n    if Relsz = ops16bits then\n      Relsz := ops32bits;\n{$ENDIF CPUX64}\n    if PInst^.OpType and otJcc = 0 then\n    begin\n      { Not Jcc ! }\n      if PInst^.OpCode in [$E0 .. $E2] then\n      begin\n        { LOOPNE/LOOPZ/LOOP }\n        if Relsz = ops8bits then\n        begin\n          if PInst^.Prefixes and Prf_AddrSize <> 0 then\n          begin\n            PQ^ := opPrfAddrSize;\n            Inc(PQ);\n          end;\n          PQ^ := PInst^.OpCode;\n          Inc(PQ);\n          PQ^ := Int8(Offset);\n          Inc(PQ);\n        end\n        else\n          case PInst^.AddrMode of\n            am16:\n              begin\n                { Dec CX ! }\n{$IFDEF CPUX64}\n                { . $49 result in REX\n                  ==> Use $FF group !\n                }\n                PQ^ := opPrfOpSize;\n                Inc(PQ);\n                PQ^ := $FF;\n                Inc(PQ);\n                PQ^ := $C9;\n                Inc(PQ);\n{$ELSE !CPUX64}\n                PQ^ := opPrfOpSize;\n                Inc(PQ);\n                PQ^ := $49;\n                Inc(PQ);\n{$ENDIF CPUX64}\n              end;\n            am32:\n              begin\n                { Dec ECX ! }\n{$IFDEF CPUX64}\n                PQ^ := $FF;\n                Inc(PQ);\n                PQ^ := $C9;\n                Inc(PQ);\n{$ELSE !CPUX64}\n                PQ^ := $49;\n                Inc(PQ);\n{$ENDIF CPUX64}\n              end;\n            am64:\n              begin\n                { Dec RCX ! }\n                PQ^ := $48; // REX.W = True !\n                Inc(PQ);\n                PQ^ := $FF;\n                Inc(PQ);\n                PQ^ := $C9;\n                Inc(PQ);\n              end;\n          end;\n        case Relsz of\n          ops16bits:\n            begin\n              Offset := Int64(Int64(PInst^.Branch.Target) - Int64(PQ) - 5);\n              PQ^ := opPrfOpSize;\n              Inc(PQ);\n              PWord(PQ)^ := LOOP_To_JccZ[PInst^.OpCode and 3];\n              Inc(PQ, 2);\n              PInt16(PQ)^ := Int16(Offset);\n              Inc(PQ, 2);\n            end;\n          ops32bits:\n            begin\n              Offset := Int64(Int64(PInst^.Branch.Target) - Int64(PQ) - 6);\n              PWord(PQ)^ := LOOP_To_JccZ[PInst^.OpCode and 3];\n              Inc(PQ, 2);\n              PInt32(PQ)^ := Int32(Offset);\n              Inc(PQ, 4);\n            end;\n          ops64bits:\n            begin\n              {\n                Dec RCX\n                Jcc @Tmp\n                Jmp @NextInst\n                @Tmp:\n                Jmp @LoopDst\n              }\n              { Insert Jcc ! }\n              PQ^ := LOOP_To_JccB[PInst^.OpCode and 3];\n              Inc(PQ);\n              PQ^ := 2;\n              Inc(PQ);\n              { Insert Jmp NextInst }\n              PQ^ := opJmpRelb;\n              Inc(PQ);\n              PQ^ := 14;\n              Inc(PQ);\n              { Insert Jmp @LoopDst }\n              InsertJmp(PQ, PInst.Branch.Target, JT_RIPZ);\n              Inc(PQ, 14);\n            end;\n        end;\n      end\n      else if PInst^.OpCode = $E3 then\n      begin\n        { JCXZ/JECX/JRCX }\n        if Relsz = ops8bits then\n        begin\n          if PInst^.Prefixes and Prf_AddrSize <> 0 then\n          begin\n            PQ^ := opPrfAddrSize;\n            Inc(PQ);\n          end;\n          PQ^ := PInst^.OpCode;\n          Inc(PQ);\n          PQ^ := Int8(Offset);\n          Inc(PQ);\n        end\n        else\n          case PInst^.AddrMode of\n            am16:\n              begin\n                { TEST CX,CX }\n                PQ^ := opPrfOpSize;\n                Inc(PQ);\n                PQ^ := opTestb;\n                Inc(PQ);\n                PQ^ := $C9; // ModRm [Mod = 3; Reg = Rm = CX = 1]\n                Inc(PQ);\n              end;\n            am32:\n              begin\n                { TEST ECX,ECX }\n                PQ^ := opTestb;\n                Inc(PQ);\n                PQ^ := $C9;\n                Inc(PQ);\n              end;\n            am64:\n              begin\n                { TEST RCX,RCX }\n                PQ^ := $48; // REX.W = True !\n                Inc(PQ);\n                PQ^ := opTestb;\n                Inc(PQ);\n                PQ^ := $C9;\n                Inc(PQ);\n              end;\n          end;\n        case Relsz of\n          ops16bits:\n            begin\n              {\n                TEST CX,CX\n                JZ @Dst\n              }\n              Offset := Int64(Int64(PInst^.Branch.Target) - Int64(PQ) - 5);\n              PQ^ := opPrfOpSize;\n              Inc(PQ);\n              PQ^ := $0F;\n              Inc(PQ);\n              PQ^ := $84; // JZ !\n              Inc(PQ);\n              PInt16(PQ)^ := Int16(Offset);\n              Inc(PQ, 2);\n            end;\n          ops32bits:\n            begin\n              {\n                TEST ECX,ECX\n                JZ @Dst\n              }\n              Offset := Int64(Int64(PInst^.Branch.Target) - Int64(PQ) - 6);\n              PQ^ := $0F;\n              Inc(PQ);\n              PQ^ := $84; // JZ !\n              Inc(PQ);\n              PInt32(PQ)^ := Int32(Offset);\n              Inc(PQ, 4);\n            end;\n          ops64bits:\n            begin\n              {\n                TEST RCX,RCX\n                JZ @Tmp\n                Jmp @NextInst\n                @Tmp:\n                Jmp @Dst\n              }\n              { Insert JZ ! }\n              PQ^ := $74;\n              Inc(PQ);\n              PQ^ := 2;\n              Inc(PQ);\n              { Insert Jmp NextInst }\n              PQ^ := opJmpRelb;\n              Inc(PQ);\n              PQ^ := 14;\n              Inc(PQ);\n              { Insert Jmp @Dst }\n              InsertJmp(PQ, PInst.Branch.Target, JT_RIPZ);\n              Inc(PQ, 14);\n            end;\n        end;\n      end;\n    end\n    else\n    begin\n      { Jcc ! }\n      NOpc := GetJccOpCode(PInst, Relsz);\n      case Relsz of\n        ops8bits:\n          begin\n            Offset := Int64(Int64(PInst^.Branch.Target) - Int64(PQ) - 2);\n            PInt8(PQ)^ := UInt8(NOpc);\n            Inc(PQ);\n            PInt8(PQ)^ := Int8(Offset);\n            Inc(PQ);\n          end;\n        ops16bits:\n          begin\n            Offset := Int64(Int64(PInst^.Branch.Target) - Int64(PQ) - 5);\n            PUInt32(PQ)^ := UInt32(NOpc);\n            Inc(PQ, 3);\n            PInt16(PQ)^ := Int16(Offset);\n            Inc(PQ, 2);\n          end;\n        ops32bits:\n          begin\n            Offset := Int64(Int64(PInst^.Branch.Target) - Int64(PQ) - 6);\n            PUInt16(PQ)^ := UInt16(NOpc);\n            Inc(PQ, 2);\n            PInt32(PQ)^ := Int32(Offset);\n            Inc(PQ, 4);\n          end;\n        ops64bits:\n          begin\n            {\n              Unfortunately there is no Jcc Rel 64bits !\n\n              ===>Original implementation<===\n              test eax,eax\n              jz @DstAddr\n\n              ===>New implementation<===\n              test eax,eax\n              Q:      jz @tmp\n              Q+2:    jmp @NextInst\n              Q+4:    @tmp:\n              Q+4:    jmp @DstAddr\n              Q+4+jmpsize:        [DstAddr]\n              @NextInstruction:\n            }\n\n            { jz @tmp is guaranteed to be 2 Bytes in length ! }\n            { Trampo.NextInstruction = Q + 4 + jmp @DstAddr Size }\n            PQ^ := PInst^.OpCode;\n            Inc(PQ);\n            PQ^ := 2;\n            Inc(PQ);\n            JmpType := GetJmpType(PByte(NativeInt(NewAddr) + 4), PInst^.Branch.Target, PByte(NativeInt(NewAddr) + 4 + 6));\n            JmpSize := JmpTypeToSize[JmpSize];\n            if JmpType > JT_REL32 then\n              Inc(JmpSize, SizeOf(Pointer));\n\n            { Jmp To Next Valid Instruction ! }\n            PQ^ := opJmpRelb;\n            Inc(PQ);\n            PQ^ := JmpSize;\n            Inc(PQ);\n            InsertJmp(PByte(NativeInt(NewAddr) + 4), PInst^.Branch.Target, JmpType, PByte(NativeInt(NewAddr) + 4 + 6));\n            Inc(PQ, JmpSize);\n          end;\n      end;\n    end;\n  finally\n    FreeMem(POpc);\n  end;\n  Result := Integer(NativeInt(PQ) - NativeInt(NewAddr));\n  if Result = 00 then\n  begin\n    Move(PInst^.Addr^, NewAddr^, PInst^.InstSize);\n    Result := PInst^.InstSize;\n  end;\nend;\n\nfunction MakeModRm(iMod, Reg, Rm: Byte): Byte; {$IFDEF MustInline}inline; {$ENDIF}\nbegin\n  Result := (iMod shl 6) or (Reg shl 3) or (Rm);\nend;\n\nfunction CorrectRipDisp(PInst: PInstruction; NewAddr: PByte): Integer;\nvar\n  Offset: Int64;\n  P: PByte;\n  rReg: Byte;\n  POpc: PByte;\n  pMR: PByte;\n  pFrst: PByte;\n  L: ShortInt;\nbegin\n  pFrst := NewAddr;\n  P := PInst^.NextInst;\n  {\n    If AddressMode is 32-bits :\n    ===> EIP + Disp32 !\n    else\n    If AddressMode is 64-bits:\n    ===> RIP + Disp32 !\n  }\n  if PInst^.AddrMode = am32 then\n    P := PByte(UInt64(P) and $FFFFFFFF);\n\n  P := PByte(Int64(P) + Int64(PInst^.Disp.Value));\n\n  Offset := Int64(Int64(P) - Int64(NewAddr) - PInst^.InstSize);\n  if Int32(Offset) <> Offset then\n  begin\n    rReg := rEAX;\n    if PInst^.ModRm.Flags and mfUsed <> 0 then\n    begin\n      Assert(PInst^.Disp.Flags and dfRip <> 0);\n      if PInst^.ModRm.Reg = rReg then\n        rReg := rECX;\n\n      { PUSH UsedReg }\n      PByte(NewAddr)^ := $50 + (rReg and $7);\n      Inc(NewAddr);\n\n{$IFDEF CPUX64}\n      PByte(NewAddr)^ := $48; // REX.W!\n      Inc(NewAddr);\n{$ENDIF CPUX64}\n      { MOV REG,Imm(NativeInt) }\n      PByte(NewAddr)^ := $B8 + (rReg and $7);\n      Inc(NewAddr);\n      PNativeInt(NewAddr)^ := NativeInt(P);\n      Inc(NewAddr, SizeOf(NativeInt));\n\n      { Set the original instruction opcodes }\n      POpc := GetMemory(MAX_INST_LENGTH_N);\n      L := GetInstOpCodes(PInst, POpc);\n\n      Move(POpc^, NewAddr^, L);\n      Inc(NewAddr, L);\n      pMR := NewAddr;\n      if (PInst^.OpKind and kGrp <> 0) or (PInst^.OpTable = tbFPU) then\n        Dec(pMR);\n\n      PByte(pMR)^ := MakeModRm($00, PInst^.ModRm.Reg, rReg);\n      Inc(pMR);\n      NewAddr := pMR;\n\n      { POP UsedReg }\n      PByte(NewAddr)^ := $58 + (rReg and $7);\n      Inc(NewAddr);\n\n      FreeMemory(POpc);\n      Result := (NativeInt(NewAddr) - NativeInt(pFrst));\n      Exit;\n    end\n    else\n      raise InterceptException.Create(SErrorRipDisp);\n  end;\n  Move(PInst^.Addr^, NewAddr^, PInst^.InstSize);\n  Inc(NewAddr, PInst^.InstSize);\n  PInt32(NativeInt(NewAddr) - SizeOf(Int32))^ := Int32(Offset);\n\n  Result := PInst^.InstSize;\nend;\n\nfunction CorrectJmpRel(PInst: PInstruction; NewAddr: PByte): Integer;\nvar\n  JmpType: Byte;\nbegin\n  JmpType := GetJmpType(NewAddr, PInst^.Branch.Target, PByte(NativeInt(NewAddr) + 6));\n  InsertJmp(NewAddr, PInst^.Branch.Target, JmpType, PByte(NativeInt(NewAddr) + 6));\n  Result := JmpTypeToSize[JmpType];\nend;\n\nfunction CorrectCallRel(PInst: PInstruction; NewAddr: PByte): Integer;\nvar\n  Offset: Int64;\n  Relsz: Byte;\n  P: PByte;\nbegin\n  P := NewAddr;\n  Offset := Int64(Int64(PInst^.Branch.Target) - Int64(P) - 6);\n  Relsz := GetInt64Size(Offset);\n{$IFDEF CPUX64}\n  { Only 32-bits relative offset is supported on x64! }\n  if Relsz < ops32bits then\n    Relsz := ops32bits;\n{$ELSE !CPUX64}\n  { Only 16/32-bits relative offset is supported on x32! }\n  if Relsz < ops16bits then\n    Relsz := ops32bits;\n{$ENDIF CPUX64}\n  case Relsz of\n    ops16bits:\n      begin\n        Offset := Int64(Int64(PInst^.Branch.Target) - Int64(P) - 4);\n        P^ := opPrfOpSize;\n        Inc(P);\n        P^ := $E8;\n        Inc(P);\n        PInt16(P)^ := Int16(Offset);\n        Inc(P, 2);\n      end;\n    ops32bits:\n      begin\n        Offset := Int64(Int64(PInst^.Branch.Target) - Int64(P) - 5);\n        P^ := $E8;\n        Inc(P);\n        PInt32(P)^ := Int32(Offset);\n        Inc(P, 4);\n      end;\n    ops64bits:\n      begin\n        {\n          64-bits Relative offset is not supported\n          ==> Map to a new opcode !\n        }\n        {\n          CALL [02]\n          Jmp @NextValidInstruction\n          dq : Call dst address !\n          @NextValidInstruction:\n\n        }\n        P^ := $FF; // Group 5 !\n        Inc(P);\n        {\n          ModRm.Mod = 00\n          ModRm.Reg = 02\n          ModRm.Rm = 05\n          ==> ModRm = $15 !\n        }\n        P^ := MakeModRm($00, $02, $05);\n        Inc(P);\n        P^ := 2;\n        Inc(P, 4);\n\n        { Jmp Next Instruction ! }\n        P^ := opJmpRelb;\n        Inc(P);\n        P^ := $08;\n        Inc(P);\n        PUInt64(P)^ := UInt64(PInst^.Branch.Target);\n        Inc(P, SizeOf(UInt64));\n      end;\n  end;\n  Result := NativeInt(P) - NativeInt(NewAddr);\n  if Result = 0 then\n  begin\n    Move(PInst^.Addr^, P^, PInst^.InstSize);\n    Result := PInst^.InstSize;\n  end;\nend;\n\nfunction MapInsts(Addr, NewAddr: PByte; Size: Integer): Integer;\nvar\n  P, Q: PByte;\n  PInst: PInstruction;\n  sz, iz, nz: Integer;\nbegin\n  { Map Data from Addr to NewAddr ! }\n  { This function will fix Relative offset & RIP displacement . }\n  Result := 0;\n  sz := 0;\n  P := Addr;\n  Q := NewAddr;\n  PInst := GetMemory(SizeOf(TInstruction));\n  FillChar(PInst^, SizeOf(TInstruction), #0);\n\n  PInst^.Archi := CPUX;\n  PInst^.NextInst := P;\n  PInst^.VirtualAddr := nil;\n\n  while sz < Size do\n  begin\n    PInst^.Addr := PInst^.NextInst;\n    iz := fDecodeInst(PInst);\n    nz := iz;\n    if PInst^.Disp.Flags and (dfUsed or dfRip) = (dfUsed or dfRip) then\n      nz := CorrectRipDisp(PInst, Q)\n    else if (PInst^.Branch.Falgs and bfRel = bfRel) then\n    begin\n      { Instruction use relative offset }\n      if (PInst^.OpType = otJMP) then\n        nz := CorrectJmpRel(PInst, Q)\n      else if (PInst^.OpType = otCALL) then\n        nz := CorrectCallRel(PInst, Q)\n      else\n        nz := CorrectJ(PInst, Q)\n    end\n    else\n      Move(PInst^.Addr^, Q^, nz);\n    Inc(Q, nz);\n    Inc(Result, nz);\n    Inc(sz, iz);\n  end;\n  FreeMemory(PInst);\nend;\n\n{$IFNDEF FPC}\n{$WARN COMPARISON_TRUE OFF}\n{$ENDIF FPC}\n\nfunction GetInstArithmeticType(PInst: PInstruction): Integer;\n  function IsInstAdd(PInst: PInstruction): Boolean;\n  begin\n    Result := False;\n    if PInst^.OpTable = tbOneByte then\n    begin\n      if (PInst^.OpCode >= $00) and (PInst^.OpCode < $06) then\n      begin\n        Result := (True);\n        Exit;\n      end;\n    end;\n    if (PInst^.OpKind = kGrp) and (PInst^.ModRm.Reg = $00) then\n    begin\n      if (PInst^.OpCode > $7F) and (PInst^.OpCode < $84) then\n      begin\n        Result := (True);\n        Exit;\n      end;\n    end;\n  end;\n  function IsInstSub(PInst: PInstruction): Boolean;\n  begin\n    Result := False;\n    if PInst^.OpTable = tbOneByte then\n    begin\n      if (PInst^.OpCode > $27) and (PInst^.OpCode < $2E) then\n      begin\n        Result := (True);\n        Exit;\n      end;\n    end;\n    if (PInst^.OpKind = kGrp) and (PInst^.ModRm.Reg = $05) then\n    begin\n      if (PInst^.OpCode > $7F) and (PInst^.OpCode < $84) then\n      begin\n        Result := (True);\n        Exit;\n      end;\n    end;\n  end;\n  function IsInstInc(PInst: PInstruction): Boolean;\n  begin\n    Result := False;\n    if (PInst^.Archi = CPUX32) and (PInst^.OpTable = tbOneByte) then\n    begin\n      if (PInst^.OpCode >= $40) and (PInst^.OpCode <= $47) then\n      begin\n        Result := (True);\n        Exit;\n      end;\n    end;\n    if (PInst^.OpKind = kGrp) and (PInst^.ModRm.Reg = $00) then\n    begin\n      if (PInst^.OpCode = $FE) or (PInst^.OpCode = $FF) then\n      begin\n        Result := (True);\n        Exit;\n      end;\n    end;\n  end;\n  function IsInstDec(PInst: PInstruction): Boolean;\n  begin\n    Result := False;\n    if (PInst^.Archi = CPUX32) and (PInst^.OpTable = tbOneByte) then\n    begin\n      if (PInst^.OpCode >= $48) and (PInst^.OpCode <= $4F) then\n      begin\n        Result := (True);\n        Exit;\n      end;\n    end;\n    if (PInst^.OpKind = kGrp) and (PInst^.ModRm.Reg = $01) then\n    begin\n      if (PInst^.OpCode = $FE) or (PInst^.OpCode = $FF) then\n      begin\n        Result := (True);\n        Exit;\n      end;\n    end;\n  end;\n\nbegin\n  { Return Instruction Arithmetic (+ or - or ..) }\n  Result := arNone;\n  if IsInstAdd(PInst) or IsInstInc(PInst) then\n    Result := (arAdd)\n  else if IsInstSub(PInst) or IsInstDec(PInst) then\n    Result := (arSub);\nend;\n{$IFNDEF FPC}\n{$WARN COMPARISON_TRUE ON}\n{$ENDIF FPC}\n\nfunction EvalArith(Arith: Integer; Value: NativeInt; Offset: NativeInt): NativeInt;\nbegin\n  Result := Value;\n  case Arith of\n    arAdd:\n      Inc(Result, Offset);\n    arInc:\n      Inc(Result);\n    arSub:\n      Dec(Result, Offset);\n    arDec:\n      Dec(Result);\n  end;\nend;\n\n{$HINTS OFF}\n\nfunction InterfaceToObj(const AIntf): TObject;\nconst\n  {\n    Delphi insert QueryInterface,_AddRef,_Release methods\n    as the last functions in the code entry.\n    => We must skip them to point to the first function declared in the interface.\n  }\n  Offset = SizeOf(Pointer) * 3;\n{$IFDEF CPUX64}\n  ObjReg = rECX;\n{$ELSE !CPUX64}\n  ObjReg = rEAX;\n{$ENDIF CPUX64}\nvar\n  Pvt, PCode: PByte;\n  Inst: TInstruction;\n  PObj: PByte;\n  imm: Int64;\n  Arith: Integer;\n  Skip: Boolean;\n  sReg: ShortInt;\nbegin\n\n  if not Assigned(@AIntf) then\n  begin\n    Result := nil;\n    Exit;\n  end;\n\n  sReg := -1;\n  PObj := PByte(AIntf);\n  FillChar(Inst, SizeOf(TInstruction), #00);\n  Inst.Archi := CPUX;\n  Pvt := PPointer(AIntf)^; // vTable !\n  PCode := PPointer(NativeInt(Pvt) + Offset)^; // Code Entry !\n  Inst.NextInst := PCode;\n  {\n    At the top of code entry delphi will generate :\n    int 3\n    add/sub eax/rcx,offset <===\n    jmp FirstFunction\n  }\n\n  while True do\n  begin\n    Inst.imm.Value := 0;\n    Inst.Addr := Inst.NextInst;\n    fDecodeInst(@Inst);\n    { Keep looping until JMP/RET ! }\n    if (Inst.Branch.Falgs and bfUsed <> 0) or (Inst.OpType = otRET) then\n      break;\n\n    Arith := GetInstArithmeticType(@Inst);\n    Skip := (Arith = arNone);\n\n    if not Skip then\n    begin\n{$IFDEF CPUX86}\n      if Inst.ModRm.iMod <> $03 then\n      begin\n        {\n          ====> stdcall ! <====\n          If the method (declared in interface)\n          calling convention is stdcall,\n          Delphi will generate :\n          add/sub [esp+offset],imm !\n        }\n        if Inst.Sib.Flags and sfUsed <> 0 then\n          sReg := Inst.Sib.Index\n        else\n          sReg := Inst.ModRm.Rm;\n        Skip := not(sReg = rESP);\n      end\n      else\n{$ENDIF CPUX86}\n      begin\n        if (Inst.ModRm.Flags and mfUsed <> 0) then\n          Skip := not((Inst.ModRm.iMod = $03) and (Inst.ModRm.Rm = ObjReg))\n        else if Arith in [arInc, arDec] then\n          { Is Inc/Dec EAX/RCX ? }\n          Skip := (Inst.OpCode and $07 <> ObjReg);\n      end;\n    end;\n\n    if not Skip then\n    begin\n      imm := Inst.imm.Value;\n      PObj := PByte(EvalArith(Arith, NativeInt(PObj), imm));\n    end;\n  end;\n\n  Result := TObject(PObj);\nend;\n\n{$HINTS ON}\n\nfunction GetInterfaceMethodPtrByIndex(const PInterface; MethodIndex: Integer): PByte;\nvar\n  Pvt: PPointer;\n  P: PPointer;\n  PDst: PByte;\n  Inst: TInstruction;\n  i: Integer;\nbegin\n  {\n    Return original method ptr\n    => Return first instruction that was\n    implemented on Interface object !\n  }\n  FillChar(Inst, SizeOf(TInstruction), #00);\n  Inst.Archi := CPUX;\n  Pvt := PPointer(PInterface)^; // Virtual Table !\n  P := Pvt;\n  Inc(P, MethodIndex);\n  P := PPointer(P)^;\n  PDst := PByte(P);\n  Inst.NextInst := PByte(P);\n  for i := 0 to 3 do\n  begin\n    Inst.Addr := Inst.NextInst;\n    fDecodeInst(@Inst);\n    if Assigned(Inst.Branch.Target) then\n    begin\n      PDst := Inst.Branch.Target;\n      break;\n    end;\n  end;\n  Result := PDst;\nend;\n\n{$IFDEF SUPPORTS_RTTI}\n\nfunction GetMethodPtrFromObjByName(Obj: TObject; const MethodName: String): Pointer;\nvar\n  LCtx: TRttiContext;\n  LType: TRttiType;\n  LMethods: TArray<TRttiMethod>;\n  LMethod: TRttiMethod;\nbegin\n  Result := nil;\n  if (not Assigned(Obj)) or (MethodName = EmptyStr) then\n    Exit;\n\n  LCtx := TRttiContext.Create;\n  LType := LCtx.GetType(Obj.ClassType);\n  LMethods := LType.GetMethods;\n  for LMethod in LMethods do\n  begin\n    if SameText(LMethod.Name, MethodName) then\n    begin\n      Result := LMethod.CodeAddress;\n      Exit;\n    end;\n  end;\nend;\n\nfunction GetInterfaceMethodPtrByName(const PInterface; const MethodName: String): PByte;\nvar\n  Obj: TObject;\nbegin\n  Result := nil;\n  if (not Assigned(@PInterface)) or (MethodName = EmptyStr) then\n    Exit;\n  Obj := InterfaceToObj(PInterface);\n  if Assigned(Obj) then\n  begin\n    Result := GetMethodPtrFromObjByName(Obj, MethodName);\n  end;\nend;\n\n{$ENDIF  SUPPORTS_RTTI}\n\nfunction GetRoot(P: PByte): PByte;\nvar\n  Inst: TInstruction;\nbegin\n  Result := P;\n  FillChar(Inst, SizeOf(TInstruction), #00);\n  Inst.Addr := P;\n  Inst.Archi := CPUX;\n  Inst.VirtualAddr := nil;\n  {\n    While the opcode is jmp and the jmp destination\n    address is known get the next jmp .\n  }\n  fDecodeInst(@Inst);\n  if (Inst.OpType = otJMP) and (Assigned(Inst.Branch.Target)) then\n    Result := GetRoot(Inst.Branch.Target);\nend;\n\nfunction IsValidDescriptor(P: PByte): Boolean;\nbegin\n  Result := CompareMem(P, PByte(@DscrSig[0]), SizeOf(DscrSig));\nend;\n\nfunction GetDescriptor(P: PByte): PDescriptor;\nvar\n  Inst: TInstruction;\n  function IsDscrpInst(PInst: PInstruction): Boolean;\n  begin\n    Result := Assigned(PInst.Branch.Target) or IsNop(PInst.Addr, 6);\n  end;\n\nbegin\n  Result := nil;\n  FillChar(Inst, SizeOf(TInstruction), #00);\n  Inst.Archi := CPUX;\n  Inst.VirtualAddr := nil;\n  { Find last JMP ! }\n  P := GetRoot(P);\n  Inst.Addr := P;\n  fDecodeInst(@Inst);\n\n  { The first instruction must be NOP ! }\n  if Inst.OpCode = opNop then\n  begin\n    Inst.Addr := Inst.NextInst;\n    fDecodeInst(@Inst);\n    if IsDscrpInst(@Inst) then\n    begin\n      Inc(P); // Skip CodeEntry !\n      Inc(P, SizeOf(TJmpMem) * (MAX_HOOKS + 1)); // Skip JmpMems !\n      { Go to the Top ! }\n      Dec(P, SizeOf(TDescriptor));\n      if IsValidDescriptor(P) then\n        Result := PDescriptor(P);\n    end;\n  end;\nend;\n\nfunction CreateNewDescriptor(): PDescriptor;\nbegin\n  { Create a new descriptor tables ! }\n  Result := AllocMem(SizeOf(TDescriptor));\n  FillNop(Result^, SizeOf(TDescriptor), False);\n  FillNop(Result^.JmpMems[0], SizeOf(TJmpMem) * (MAX_HOOKS + 1), True);\n\n  { A valid descriptor have a valid signature . }\n  CopyMemory(Result, PByte(@DscrSig[0]), DscrSigSize);\n  Result^.nHook := 0;\n  Result^.Flags := 0;\n  Result^.ExMem := nil;\nend;\n\nprocedure InsertDescriptor(PAt: PByte; PDscr: PDescriptor);\nconst\n  { JMP from Target to Code Entry }\n  kJmpCE = 1;\n  { JMP from Target to Temporal address than JMP to Code Entry }\n  kJmpTmpJmpCE = 2;\n  { JMP from Target to Temporal address than JMP (Rip Zero) to Code Entry }\n  kJmpTmpJmpRipZCE = 3;\n  { JMP (Rip Zero) from Target to Code Entry }\n  kJmpRipZCE = 4;\n\nvar\n  fJmpType: Byte; { First JMP }\n{$IFDEF CPUX64}\n  sJmpType: Byte; { Second JMP (if used !) }\n  Tmp: PByte;\n{$ENDIF CPUX64}\n  JmpKind: Byte;\n  P, T: PByte;\n  JmpSize: Byte;\n  Inst: TInstruction;\n  Sb: Byte;\n  OrgAccess: DWORD;\n  Tsz: Integer;\n  PExMem: PByte;\n  LPExMem: PByte;\nbegin\n  Sb := 0;\n  P := PAt;\n  PDscr^.OrgPtr := P;\n  fJmpType := GetJmpType(P, @PDscr^.CodeEntry, @PDscr^.DscrAddr);\n{$IFDEF CPUX64}\n  Tmp := nil;\n  PExMem := TryAllocMemAt(P, SizeOfAlloc, PAGE_EXECUTE_READWRITE);\n  LPExMem := PExMem;\n  sJmpType := JT_NONE;\n  JmpKind := kJmpRipZCE;\n  { Try to find the perfect jump instruction ! }\n  {\n    That's mean that we try to avoid using tJmpRelN on TargetProc .\n    ==> Because it use more than 6 bytes in length .\n  }\n  if JmpTypeToSize[fJmpType] > 6 then\n  begin\n    Tmp := PExMem;\n    Inc(PExMem, TmpSize);\n    if Assigned(Tmp) then\n    begin\n      JmpKind := kJmpRipZCE;\n      fJmpType := GetJmpType(P, Tmp, Tmp + 6);\n      if JmpTypeToSize[fJmpType] < 7 then\n      begin\n        JmpKind := kJmpTmpJmpRipZCE;\n        sJmpType := GetJmpType(Tmp, @PDscr^.CodeEntry, Tmp + 6 + 8);\n        if JmpTypeToSize[sJmpType] < 7 then\n          JmpKind := kJmpTmpJmpCE;\n      end;\n    end;\n  end\n  else\n  begin\n    JmpKind := kJmpCE;\n  end;\n{$ELSE !CPUX64}\n  PExMem := TryAllocMemAt(nil, SizeOfAlloc, PAGE_EXECUTE_READWRITE);\n  JmpKind := kJmpCE;\n  LPExMem := PExMem;\n{$ENDIF CPUX64}\n  FillChar(Inst, SizeOf(TInstruction), #00);\n  Inst.Archi := CPUX;\n  Inst.NextInst := P;\n  Inst.VirtualAddr := nil;\n\n  JmpSize := JmpTypeToSize[fJmpType];\n\n  while Sb < JmpSize do\n  begin\n    if Inst.OpType = otRET then\n      raise InterceptException.Create(SErrorSmallFunctionSize);\n    Inst.Addr := Inst.NextInst;\n    Inc(Sb, fDecodeInst(@Inst));\n  end;\n\n  if Sb > TrampoSize then\n    raise InterceptException.Create(SErrorBigTrampoSize);\n\n  { Trampoline momory }\n  T := PExMem;\n  FillNop(T^, TrampoSize, False);\n\n  PDscr^.Trampo := AllocMem(SizeOf(TTrampoInfo));\n  PDscr^.Trampo^.PData := AllocMem(Sb + 6);\n  FillNop(PDscr^.Trampo^.PData^, Sb + 6, False);\n  { Save original target routine instruction . }\n  Move(P^, PDscr^.Trampo^.PData^, Sb);\n  PDscr^.Trampo^.Addr := T; // Pointer to the first trampoline instruction.\n  PDscr^.Trampo^.Size := Sb; // Size of stolen instructions .\n\n  Tsz := MapInsts(P, T, Sb);\n  OrgAccess := SetMemPermission(P, Sb, PAGE_EXECUTE_READWRITE);\n  try\n    FillNop(P^, Sb, False);\n    case JmpKind of\n      kJmpCE:\n        begin\n          { A very good jump ! }\n          {\n            TargetProc :\n            JMP @PDscr^.CodeEntry\n          }\n          InsertJmp(P, @PDscr^.CodeEntry, fJmpType, @PDscr^.DscrAddr);\n        end;\n{$IFDEF CPUX64}\n      kJmpTmpJmpCE:\n        begin\n          {\n            TargetProc :\n            JMP @Tmp ==> Tmp is allocated nearly from TargetProc !\n\n            Tmp:\n            JMP @PDscr^.CodeEntry\n          }\n          InsertJmp(P, Tmp, fJmpType, Tmp + 6);\n          InsertJmp(Tmp, @PDscr^.CodeEntry, sJmpType, Tmp + 6 + 8);\n        end;\n      kJmpTmpJmpRipZCE:\n        begin\n          {\n            TargetProc :\n            JMP @Tmp ==> Tmp is allocated nearly from TargetProc !\n\n            Tmp:\n            JMP @PDscr^.CodeEntry  ==> JT_RIPZ\n          }\n          InsertJmp(P, Tmp, fJmpType, Tmp + 6);\n          InsertJmp(Tmp, @PDscr^.CodeEntry, JT_RIPZ, nil);\n        end;\n      kJmpRipZCE:\n        begin\n          {\n            Not a good jump !\n\n            TargetProc :\n            JMP @PDscr^.CodeEntry  ==> JT_RIPZ\n          }\n          InsertJmp(P, @PDscr^.CodeEntry, JT_RIPZ, nil);\n        end;\n{$ENDIF CPUX64}\n    end;\n\n    {\n      Insert a JMP instruction after the stolen instructions\n      on the trampoline.\n      ==> This JMP will return to TargetProc to allow\n      executing originals instructions.\n    }\n{$IFDEF CPUX64}\n    InsertJmp(T + Tsz, P + Sb, JT_RIPZ);\n{$ELSE !CPUX64}\n    InsertJmp(PByte(NativeInt(T) + Tsz), PByte(NativeInt(P) + Sb), JT_MEM32, PByte(NativeInt(T) + Tsz + 6));\n{$ENDIF CPUX64}\n    { Save LPExMem ==> we need it when deleting descriptor }\n    PDscr^.ExMem := LPExMem;\n\n    SetMemPermission(LPExMem, SizeOfAlloc, PAGE_EXECUTE_READWRITE);\n    SetMemPermission(PDscr, SizeOf(TDescriptor), PAGE_EXECUTE_READWRITE);\n  finally\n    SetMemPermission(P, Sb, OrgAccess);\n  end;\nend;\n\nprocedure MadExceptFreeMem(P: Pointer);\nvar\n  Page: Pointer;\n  mbi: TMemoryBasicInformation;\n  Permission: DWORD;\nbegin\n  if InternalFuncs.VirtualQuery(P, mbi, SizeOf(mbi)) <> 0 then\n  begin\n    Page := mbi.BaseAddress;\n    Permission := SetMemPermission(Page, SysInfo.dwPageSize, PAGE_READWRITE);\n    FreeMem(P);\n    SetMemPermission(Page, SysInfo.dwPageSize, Permission);\n  end\n  else\n    FreeMem(P);\nend;\n\nfunction GetNextHookPtrFromTrampoline(TrampoLine: Pointer): PNextHook;\nbegin\n  if Assigned(TrampoLine) then\n  begin\n    Result := PNextHook(NativeInt(TrampoLine) - SizeOf(TNextHook));\n    if Result^.Signature = TrampolineSignature then\n      Exit;\n  end;\n  raise DetourException.Create(SErrorInvalidTrampoline);\nend;\n\nfunction AddHook(PDscr: PDescriptor; InterceptProc: PByte; Param: Pointer; Options: TInterceptOptions): PByte;\nvar\n  n: ShortInt;\n  NxHook: PByte;\n  LTlsRecursionLevelIndex: DWORD;\nbegin\n  {\n    Return a pointer to a function that can\n    call next installed Hooks.\n  }\n  n := PDscr^.nHook;\n  if n + 1 > MAX_HOOKS then\n    raise InterceptException.Create(SErrorMaxHook);\n\n  { Alloc memory for the NextHook ! }\n  NxHook := AllocMem(TrampoSize);\n  Result := NxHook;\n\n  FillNop(Result^, TrampoSize, False);\n\n  PNextHook(Result)^.PDscr := PDscr;\n  PNextHook(Result)^.ID := n + 1;\n  PNextHook(Result)^.threadid := GetCurrentThreadId();\n  PNextHook(Result)^.Param := Param;\n  PNextHook(Result)^.Signature := TrampolineSignature;\n  PNextHook(Result)^.InterceptOptions := Options;\n  if ioRecursive in Options then\n  begin\n    LTlsRecursionLevelIndex := TlsAlloc();\n    if LTlsRecursionLevelIndex <> TLS_OUT_OF_INDEXES then\n      PNextHook(Result)^.TlsRecursionLevelIndex := LTlsRecursionLevelIndex\n    else\n      raise DetourException.Create(SErrorTlsOutOfIndexes);\n  end;\n  Inc(Result, SizeOf(TNextHook));\n\n  { Redirect code to InterceptProc ! }\n  InsertJmp(@PDscr^.JmpMems[n], InterceptProc, JT_MEMN, @PDscr^.JmpAddrs[n]);\n  { Redirect code to TrampoLine ! }\n  InsertJmp(@PDscr^.JmpMems[n + 1], PDscr^.Trampo^.Addr, JT_MEMN, @PDscr^.JmpAddrs[n + 1]);\n  { Redirect code to next hook ! }\n  InsertJmp(Result, @PDscr^.JmpMems[n + 1], JT_MEMN, PByte(NativeInt(Result) + 6));\n  Inc(PDscr^.nHook);\n\n  SetMemPermission(Result, JmpTypeToSize[JT_RIPZ], PAGE_EXECUTE_READWRITE);\nend;\n\nfunction InstallHook(TargetProc, InterceptProc: PByte; Param: Pointer; Options: TInterceptOptions): PByte;\nvar\n  P: PByte;\n  PDscr: PDescriptor;\nbegin\n  if not Assigned(TargetProc) then\n    raise InterceptException.Create(SErrorInvalidTargetProc);\n\n  if not Assigned(InterceptProc) then\n    raise InterceptException.Create(SErrorInvalidInterceptProc);\n\n  PDscr := GetDescriptor(TargetProc);\n  if not Assigned(PDscr) then\n  begin\n    P := GetRoot(TargetProc);\n    PDscr := CreateNewDescriptor();\n    try\n      InsertDescriptor(P, PDscr);\n    except\n      FreeMem(PDscr);\n      raise;\n    end;\n  end;\n  Result := AddHook(PDscr, InterceptProc, Param, Options);\nend;\n\nprocedure RemoveDescriptor(PDscr: PDescriptor);\nvar\n  OrgAccess: DWORD;\n  P: PByte;\n  sz: Integer;\n  vr: Boolean;\nbegin\n  P := PDscr^.OrgPtr;\n  sz := PDscr^.Trampo^.Size;\n\n  OrgAccess := SetMemPermission(P, sz, PAGE_EXECUTE_READWRITE);\n  try\n    SetMemPermission(PDscr^.ExMem, TrampoSize, PAGE_EXECUTE_READWRITE);\n\n    { Restore the old stolen instructions ! }\n    Move(PDscr^.Trampo^.PData^, PDscr^.OrgPtr^, PDscr^.Trampo^.Size);\n\n    FillNop(PDscr^.ExMem^, SizeOfAlloc, False);\n    FreeMem(PDscr^.Trampo^.PData);\n    FreeMem(PDscr^.Trampo);\n\n    if Assigned(PDscr^.ExMem) then\n    begin\n      vr := InternalFuncs.VirtualFree(PDscr^.ExMem, 0, MEM_RELEASE);\n      if not vr then\n        RaiseLastOSError;\n    end;\n\n    FillNop(PDscr^, SizeOf(TDescriptor), False);\n{$IFDEF FIX_MADEXCEPT}\n    MadExceptFreeMem(PDscr);\n{$ELSE !FIX_MADEXCEPT}\n    FreeMem(PDscr);\n{$ENDIF FIX_MADEXCEPT}\n  finally\n    SetMemPermission(P, sz, OrgAccess);\n  end;\nend;\n\nfunction RemoveHook(TrampoLine: PByte): Integer;\nvar\n  PNxtHook: PNextHook;\n  PDscr: PDescriptor;\n  n: Byte;\nbegin\n  if not Assigned(TrampoLine) then\n    raise InterceptException.Create(SErrorInvalidTrampoline);\n\n  PNxtHook := GetNextHookPtrFromTrampoline(TrampoLine);\n  if not Assigned(PNxtHook) then\n    raise InterceptException.Create(SErrorInvalidTrampoline);\n\n  PDscr := PNxtHook^.PDscr;\n  if not IsValidDescriptor(PByte(PDscr)) then\n    raise InterceptException.Create(SErrorInvalidDescriptor);\n\n  n := PNxtHook^.ID;\n  Dec(PDscr^.nHook);\n\n  PDscr^.JmpAddrs[n - 1] := nil;\n  { Remove JMP from descriptor table }\n  FillNop(PByte(@PDscr^.JmpMems[n - 1])^, SizeOf(TJmpMem), True);\n\n  {\n    Return the number of hooks\n    that are still alive !\n  }\n  Result := PDscr^.nHook;\n\n  if Result = 0 then\n    RemoveDescriptor(PDscr);\n\n  if ioRecursive in PNxtHook^.InterceptOptions then\n    TlsFree(PNxtHook^.TlsRecursionLevelIndex);\n\n{$IFDEF FIX_MADEXCEPT}\n    MadExceptFreeMem(PNxtHook);\n{$ELSE !FIX_MADEXCEPT}\n    FreeMem(PNxtHook);\n{$ENDIF FIX_MADEXCEPT}\n\nend;\n\n{ ======================================= InterceptCreate ======================================= }\n\nfunction InterceptCreate(const TargetProc, InterceptProc: Pointer; const Param: Pointer = nil;\n  const Options: TInterceptOptions = DefaultInterceptOptions): Pointer;\nbegin\n  Result := InstallHook(TargetProc, InterceptProc, Param, Options);\nend;\n\nfunction InterceptCreate(const TargetInterface; MethodIndex: Integer; const InterceptProc: Pointer; const Param: Pointer = nil;\n  const Options: TInterceptOptions = DefaultInterceptOptions): Pointer;\nvar\n  P: PByte;\nbegin\n  Result := nil;\n  if not Assigned(@TargetInterface) then\n    Exit;\n  P := GetInterfaceMethodPtrByIndex(TargetInterface, MethodIndex);\n  if Assigned(P) then\n  begin\n    Result := InterceptCreate(P, InterceptProc, Param, Options);\n  end;\nend;\n\nfunction InterceptCreate(const Module, MethodName: string; const InterceptProc: Pointer; const Param: Pointer = nil;\n  const Options: TInterceptOptions = DefaultInterceptOptions): Pointer;\nvar\n  pOrgPointer: Pointer;\n  LModule: THandle;\nbegin\n  { RRUZ's idea ==> Looks great ! }\n  Result := nil;\n  LModule := GetModuleHandle(PChar(Module));\n  if (LModule = 0) and (ioForceLoad in Options) then\n    LModule := LoadLibrary(PChar(Module));\n\n  if LModule <> 0 then\n  begin\n    pOrgPointer := GetProcAddress(LModule, PChar(MethodName));\n    if Assigned(pOrgPointer) then\n      Result := InterceptCreate(pOrgPointer, InterceptProc, Param, Options);\n  end;\nend;\n\nprocedure InterceptCreate(const TargetProc, InterceptProc: Pointer; var TrampoLine: Pointer; const Param: Pointer = nil;\n  const Options: TInterceptOptions = DefaultInterceptOptions);\nbegin\n  TrampoLine := InstallHook(TargetProc, InterceptProc, Param, Options);\nend;\n\n{$IFDEF SUPPORTS_RTTI}\n\nfunction InterceptCreate(const TargetInterface; const MethodName: String; const InterceptProc: Pointer; const Param: Pointer = nil;\n  const Options: TInterceptOptions = DefaultInterceptOptions): Pointer; overload;\nvar\n  P: PByte;\nbegin\n  { Interface support }\n  Result := nil;\n  if (not Assigned(@TargetInterface)) or (MethodName = EmptyStr) then\n    Exit;\n\n  P := GetInterfaceMethodPtrByName(TargetInterface, MethodName);\n  if Assigned(P) then\n    Result := InterceptCreate(P, InterceptProc);\nend;\n\n{$ENDIF SUPPORTS_RTTI}\n{ ======================================= InterceptRemove ======================================= }\n\nfunction InterceptRemove(const TrampoLine: Pointer): Integer;\nbegin\n  if Assigned(TrampoLine) then\n    Result := RemoveHook(TrampoLine)\n  else\n    Result := -1;\nend;\n\n{ ======================================= GetHookCount ======================================= }\n\nfunction GetHookCount(const TargetProc: Pointer): Integer;\nvar\n  PDscr: PDescriptor;\nbegin\n  { Return the number of installed hooks. }\n  if Assigned(TargetProc) then\n  begin\n    PDscr := GetDescriptor(TargetProc);\n    if Assigned(PDscr) then\n    begin\n      Result := PDscr^.nHook;\n      Exit;\n    end;\n  end\n  else\n    raise InterceptException.Create(SErrorInvalidTargetProc);\n  Result := 0;\nend;\n\nfunction GetHookCount(const TargetInterface; MethodIndex: Integer): Integer; overload;\nvar\n  P: PByte;\nbegin\n  P := GetInterfaceMethodPtrByIndex(TargetInterface, MethodIndex);\n  Result := GetHookCount(P);\nend;\n{$IFDEF SUPPORTS_RTTI}\n\nfunction GetHookCount(const TargetInterface; const MethodName: String): Integer; overload;\nvar\n  P: PByte;\nbegin\n  { Interface support }\n  P := GetInterfaceMethodPtrByName(TargetInterface, MethodName);\n  Result := GetHookCount(P);\nend;\n{$ENDIF  SUPPORTS_RTTI}\n{ ======================================= IsHooked ======================================= }\n\nfunction IsHooked(const TargetProc: Pointer): Boolean;\nbegin\n  Result := GetHookCount(TargetProc) > 0;\nend;\n\nfunction IsHooked(const TargetInterface; MethodIndex: Integer): Boolean; overload;\nvar\n  P: PByte;\nbegin\n  P := GetInterfaceMethodPtrByIndex(TargetInterface, MethodIndex);\n  Result := IsHooked(P);\nend;\n\n{$IFDEF SUPPORTS_RTTI}\n\nfunction IsHooked(const TargetInterface; const MethodName: String): Boolean; overload;\nvar\n  P: PByte;\nbegin\n  { Interface support }\n  P := GetInterfaceMethodPtrByName(TargetInterface, MethodName);\n  Result := IsHooked(P);\nend;\n{$ENDIF  SUPPORTS_RTTI}\n{ ======================================= Patch ======================================= }\n\nfunction PatchVt(const TargetInterface; MethodIndex: Integer; InterceptProc: Pointer): Pointer;\nvar\n  vt: PPointer;\n  P, DstAddr: PPointer;\n  Q: PByte;\n  OrgAccess: DWORD;\n  PInfo: PTrampoDataVt;\nbegin\n  {\n    NB: PatchVt does not support multi hook !!\n    PatchVt will patch only vtable !!\n  }\n  Result := nil;\n  if not Assigned(@TargetInterface) then\n    Exit;\n  if not Assigned(InterceptProc) then\n    Exit;\n\n  try\n    vt := PPointer(TargetInterface)^;\n    P := vt;\n    Inc(P, MethodIndex);\n    DstAddr := P^; // address !\n\n    OrgAccess := SetMemPermission(P, 32, PAGE_EXECUTE_READWRITE);\n    try\n      P^ := InterceptProc;\n    finally\n      SetMemPermission(P, 32, OrgAccess);\n    end;\n\n    Result := InternalFuncs.VirtualAlloc(nil, 32, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);\n    SetMemPermission(Result, 32, PAGE_EXECUTE_READWRITE);\n    PInfo := Result;\n    PInfo^.vAddr := P;\n    PInfo^.Addr := DstAddr;\n    Inc(PByte(Result), SizeOf(TTrampoDataVt));\n\n    Q := Result;\n{$IFDEF CPUX64}\n    { Use JMP RipZero ! }\n    PWord(Q)^ := opJmpMem;\n    Inc(Q, 2);\n    PInt32(Q)^ := $00;\n    Inc(Q, 4);\n    PNativeInt(Q)^ := NativeInt(DstAddr);\n{$ELSE !CPUX64}\n    PWord(Q)^ := opJmpMem;\n    Inc(Q, 2);\n    PUInt32(Q)^ := UInt32(NativeInt(Q) + 4);\n    PUInt32(NativeInt(Q) + 4)^ := UInt32(DstAddr);\n{$ENDIF CPUX64}\n  finally\n  end;\nend;\n\nfunction UnPatchVt(const TrampoLine: Pointer): Boolean;\nvar\n  OrgAccess: DWORD;\n  PInfo: PTrampoDataVt;\nbegin\n  if not Assigned(TrampoLine) then\n  begin\n    Result := False;\n    Exit;\n  end;\n\n  try\n    PInfo := PTrampoDataVt(NativeInt(TrampoLine) - SizeOf(TTrampoDataVt));\n    OrgAccess := SetMemPermission(PInfo^.vAddr, 32, PAGE_EXECUTE_READWRITE);\n    try\n      PPointer(PInfo^.vAddr)^ := PInfo^.Addr;\n    finally\n      SetMemPermission(PInfo^.vAddr, 32, OrgAccess);\n    end;\n    Result := InternalFuncs.VirtualFree(TrampoLine, 0, MEM_RELEASE);\n  finally\n  end;\nend;\n\n{ ======================================= Trampoline misc =================================== }\n\nfunction GetCreatorThreadIdFromTrampoline(var TrampoLine): TThreadId;\nvar\n  PNxtHook: PNextHook;\nbegin\n  PNxtHook := GetNextHookPtrFromTrampoline(PPointer(@TrampoLine)^);\n  Result := PNxtHook^.threadid;\nend;\n\nfunction GetTrampolineParam(var TrampoLine): Pointer;\nvar\n  PNxtHook: PNextHook;\nbegin\n  PNxtHook := GetNextHookPtrFromTrampoline(PPointer(@TrampoLine)^);\n  Result := PNxtHook^.Param;\nend;\n\n{ ======================================= Recursive Section ======================================= }\n\nfunction EnterRecursiveSection(var TrampoLine; MaxRecursionLevel: NativeInt = 0): Boolean;\nvar\n  PNxtHook: PNextHook;\n  RecursionLevel: NativeInt;\nbegin\n  PNxtHook := GetNextHookPtrFromTrampoline(PPointer(@TrampoLine)^);\n  if ioRecursive in PNxtHook^.InterceptOptions then\n  begin\n    RecursionLevel := NativeInt(TlsGetValue(PNxtHook^.TlsRecursionLevelIndex));\n    Result := RecursionLevel <= MaxRecursionLevel;\n    if Result then\n    begin\n      Inc(RecursionLevel);\n      TlsSetValue(PNxtHook^.TlsRecursionLevelIndex, Pointer(RecursionLevel));\n    end;\n  end\n  else\n    raise DetourException.Create(SErrorRecursiveSectionUnsupported);\nend;\n\nfunction ExitRecursiveSection(var TrampoLine): Boolean;\nvar\n  PNxtHook: PNextHook;\n  RecursionLevel: NativeInt;\nbegin\n  PNxtHook := GetNextHookPtrFromTrampoline(PPointer(@TrampoLine)^);\n  if ioRecursive in PNxtHook^.InterceptOptions then\n  begin\n    RecursionLevel := NativeInt(TlsGetValue(PNxtHook^.TlsRecursionLevelIndex));\n    Result := RecursionLevel >= 0;\n    if Result then\n    begin\n      Dec(RecursionLevel);\n      TlsSetValue(PNxtHook^.TlsRecursionLevelIndex, Pointer(RecursionLevel));\n    end;\n  end\n  else\n    raise DetourException.Create(SErrorRecursiveSectionUnsupported);\nend;\n\n{ ======================================= Transaction ======================================= }\nfunction CountThreadCallBack(ID: DWORD; Param: Pointer): BOOL;\nbegin\n  Assert(Assigned(Param));\n  Inc(PInteger(Param)^);\n  Result := True;\nend;\n\nfunction SuspendOrResumeThread(threadid: DWORD; Suspend: Boolean): DWORD;\nvar\n  hThread: THandle;\nbegin\n  hThread := OpenThread(THREAD_SUSPEND_RESUME, False, threadid);\n  if hThread <> THandle(0) then\n  begin\n    if Suspend then\n      Result := SuspendThread(hThread)\n    else\n      Result := ResumeThread(hThread);\n    CloseHandle(hThread);\n  end\n  else\n    Result := DWORD(-1);\nend;\n\nfunction SuspendThreadCallBack(ID: DWORD; Param: Pointer): BOOL;\nvar\n  PStruct: PTransactionStruct;\n  SuspendCount: DWORD;\nbegin\n  Assert(Assigned(Param));\n  PStruct := PTransactionStruct(Param);\n  if ID <> PStruct^.TID then\n  begin\n    SuspendCount := SuspendOrResumeThread(ID, True);\n    if SuspendCount <> DWORD(-1) then\n    // thread's previously was running  .\n    begin\n      { Only add threads that was running before suspending them ! }\n      PStruct^.SuspendedThreads^[PStruct^.SuspendedThreadCount] := ID;\n      Inc(PStruct^.SuspendedThreadCount);\n    end;\n  end;\n  Result := True;\nend;\n\nfunction BeginTransaction(Options: TTransactionOptions = [toSuspendThread]): THandle;\nvar\n  PStruct: PTransactionStruct;\n  ThreadCount: Integer;\n  P: Pointer;\n  ThreadHandle: THandle;\nbegin\n  EnterLook(FLock);\n  try\n    ThreadHandle := GetCurrentThread();\n    PStruct := GetMemory(SizeOf(TTransactionStruct));\n    FillChar(PStruct^, SizeOf(TTransactionStruct), #00);\n    PStruct^.Options := Options;\n    PStruct^.PID := GetCurrentProcessId();\n    PStruct^.TID := GetCurrentThreadId();\n    PStruct^.ThreadPriority := GetThreadPriority(ThreadHandle);\n    SetThreadPriority(ThreadHandle, THREAD_PRIORITY_TIME_CRITICAL);\n    Result := THandle(PStruct);\n    if toSuspendThread in Options then\n    begin\n      ThreadCount := 0;\n      EnumProcessThreads(PStruct^.PID, @CountThreadCallBack, @ThreadCount);\n      if ThreadCount > 1 then\n      begin\n        P := GetMemory(ThreadCount * 2 * SizeOf(DWORD));\n        PStruct^.SuspendedThreads := P;\n        EnumProcessThreads(PStruct^.PID, @SuspendThreadCallBack, PStruct);\n      end;\n    end;\n  finally\n    LeaveLook(FLock);\n  end;\nend;\n\nfunction EndTransaction(Handle: THandle): Boolean;\nvar\n  PStruct: PTransactionStruct;\n  i: Integer;\nbegin\n  EnterLook(FLock);\n  Result := True;\n  PStruct := PTransactionStruct(Handle);\n  try\n    if PStruct^.SuspendedThreadCount > 0 then\n    begin\n      for i := 0 to PStruct^.SuspendedThreadCount - 1 do\n      begin\n        SuspendOrResumeThread(PStruct^.SuspendedThreads^[i], False);\n      end;\n      FreeMemory(PStruct^.SuspendedThreads);\n    end;\n    SetThreadPriority(GetCurrentThread(), PStruct^.ThreadPriority);\n    FreeMemory(PTransactionStruct(Handle));\n  finally\n    LeaveLook(FLock);\n  end;\nend;\n\n{$IFDEF SUPPORTS_GENERICS}\n{ TIntercept<T,U> }\n\nfunction TIntercept<T, U>.TToPointer(const A): Pointer;\nbegin\n  Result := Pointer(A);\nend;\n\nfunction TIntercept<T, U>.PointerToT(const P): T;\nbegin\n  Result := T(P);\nend;\n\nfunction TIntercept<T, U>.EnsureTIsMethod(): Boolean;\nvar\n  LPInfo: PTypeInfo;\nbegin\n  Result := SizeOf(T) = SizeOf(Pointer);\n  if Result then\n  begin\n    LPInfo := TypeInfo(T);\n    if LPInfo.Kind = tkProcedure then\n      Exit\n    else\n      raise DetourException.Create(SErrorInvalidTType);\n  end;\nend;\n\nconstructor TIntercept<T, U>.Create(const TargetProc, InterceptProc: T; const AParam: U; const AInterceptOptions: TInterceptOptions = DefaultInterceptOptions);\nbegin\n  EnsureTIsMethod();\n  FCreatorThreadId := GetCurrentThreadId();\n  FInterceptOptions := AInterceptOptions;\n  FParam := AParam;\n  FTrampolinePtr := InterceptCreate(TToPointer(TargetProc), TToPointer(InterceptProc), @FParam, AInterceptOptions);\n  FNextHook := PointerToT(FTrampolinePtr);\nend;\n\nfunction TIntercept<T, U>.GetTrampoline(): T;\nbegin\n  Result := FNextHook;\nend;\n\nfunction TIntercept<T, U>.GetParam(): U;\nbegin\n  Result := FParam;\nend;\n\nfunction TIntercept<T, U>.GetCreatorThreadId(): TThreadId;\nbegin\n  Result := FCreatorThreadId;\nend;\n\nfunction TIntercept<T, U>.GetInterceptOptions(): TInterceptOptions;\nbegin\n  Result := FInterceptOptions;\nend;\n\nfunction TIntercept<T, U>.EnterRecursive(MaxRecursionLevel: NativeInt = 0): Boolean;\nbegin\n  Result := EnterRecursiveSection(FTrampolinePtr, MaxRecursionLevel);\nend;\n\nfunction TIntercept<T, U>.ExitRecursive(): Boolean;\nbegin\n  Result := ExitRecursiveSection(FTrampolinePtr);\nend;\n\ndestructor TIntercept<T, U>.Destroy();\nbegin\n  InterceptRemove(TToPointer(FNextHook));\n  inherited;\nend;\n\n{ TIntercept<T> }\nconstructor TIntercept<T>.Create(const TargetProc, InterceptProc: T; const AParam: Pointer = nil;\n  const AInterceptOptions: TInterceptOptions = DefaultInterceptOptions);\nbegin\n  inherited Create(TargetProc, InterceptProc, AParam, InterceptOptions);\nend;\n\n{$ENDIF SUPPORTS_GENERICS}\n{ ======================================= Initialization ======================================= }\n\nprocedure InitInternalFuncs();\n\n  function CloneFunc(Func: PByte): PByte;\n  var\n    mb, ns, Sb, fn: Byte;\n    P: PByte;\n    Inst: TInstruction;\n  begin\n    Sb := 0;\n    Func := GetRoot(Func);\n    Result := VirtualAlloc(nil, 64, MEM_RESERVE or MEM_COMMIT, PAGE_EXECUTE_READWRITE);\n    P := Result;\n    mb := JmpTypeToSize[JT_RIPZ];\n    FillChar(Inst, SizeOf(TInstruction), #00);\n    Inst.Archi := CPUX;\n    Inst.NextInst := Func;\n    while Sb <= mb do\n    begin\n      Inst.Addr := Inst.NextInst;\n      ns := fDecodeInst(@Inst);\n      Inc(Sb, ns);\n    end;\n    fn := MapInsts(Func, P, Sb);\n    Inc(P, fn);\n{$IFDEF CPUX64}\n    InsertJmp(P, PByte(NativeInt(Func) + Sb), JT_RIPZ);\n{$ELSE !CPUX64}\n    InsertJmp(P, PByte(NativeInt(Func) + Sb), JT_REL32);\n{$ENDIF CPUX64}\n  end;\n\nbegin\n{$IFDEF HOOK_INTERNAL_FUNCTIONS}\n  @InternalFuncs.VirtualAlloc := CloneFunc(@VirtualAlloc);\n  @InternalFuncs.VirtualFree := CloneFunc(@VirtualFree);\n  @InternalFuncs.VirtualProtect := CloneFunc(@VirtualProtect);\n  @InternalFuncs.VirtualQuery := CloneFunc(@VirtualQuery);\n  @InternalFuncs.FlushInstructionCache := CloneFunc(@FlushInstructionCache);\n  @InternalFuncs.GetCurrentProcess := CloneFunc(@GetCurrentProcess);\n{$ELSE !HOOK_INTERNAL_FUNCTIONS}\n  @InternalFuncs.VirtualAlloc := @VirtualAlloc;\n  @InternalFuncs.VirtualFree := @VirtualFree;\n  @InternalFuncs.VirtualProtect := @VirtualProtect;\n  @InternalFuncs.VirtualQuery := @VirtualQuery;\n  @InternalFuncs.FlushInstructionCache := @FlushInstructionCache;\n  @InternalFuncs.GetCurrentProcess := @GetCurrentProcess;\n{$ENDIF HOOK_INTERNAL_FUNCTIONS}\nend;\n\nprocedure FreeInternalFuncs;\nbegin\n{$IFDEF HOOK_INTERNAL_FUNCTIONS}\n  InternalFuncs.VirtualFree(@InternalFuncs.VirtualAlloc, 0, MEM_RELEASE);\n  InternalFuncs.VirtualFree(@InternalFuncs.VirtualProtect, 0, MEM_RELEASE);\n  InternalFuncs.VirtualFree(@InternalFuncs.VirtualQuery, 0, MEM_RELEASE);\n  InternalFuncs.VirtualFree(@InternalFuncs.FlushInstructionCache, 0, MEM_RELEASE);\n  InternalFuncs.VirtualFree(@InternalFuncs.GetCurrentProcess, 0, MEM_RELEASE);\n  // VirtualFree must be the last one !\n  InternalFuncs.VirtualFree(@InternalFuncs.VirtualFree, 0, MEM_RELEASE);\n{$ENDIF HOOK_INTERNAL_FUNCTIONS}\nend;\n\ninitialization\n\n{$IFDEF SUPPORTS_MONITOR}\n  FLock := TObject.Create();\n{$ELSE SUPPORTS_MONITOR}\n  FLock := TCriticalSection.Create();\n{$ENDIF SUPPORTS_MONITOR}\nGetSystemInfo(SysInfo);\nSizeOfAlloc := SysInfo.dwPageSize;\nif SizeOfAlloc < (TmpSize + TrampoSize + 64) then\n  SizeOfAlloc := (TmpSize + TrampoSize + 64);\n{$IFDEF FPC}\nOpenThread := nil;\n{$ELSE !FPC}\n@OpenThread := nil;\n{$ENDIF !FPC}\nFreeKernel := False;\n\nhKernel := GetModuleHandle(kernel32);\nif hKernel <= 0 then\nbegin\n  hKernel := LoadLibrary(kernel32);\n  FreeKernel := (hKernel > 0);\nend;\n\nif hKernel > 0 then\nbegin\n{$IFDEF FPC}\n  @OpenThread := GetProcAddress(hKernel, 'OpenThread');\n  @CreateToolhelp32Snapshot := GetProcAddress(hKernel, 'CreateToolhelp32Snapshot');\n  @Thread32First := GetProcAddress(hKernel, 'Thread32First');\n  @Thread32Next := GetProcAddress(hKernel, 'Thread32Next');\n{$ELSE !FPC}\n  @OpenThread := GetProcAddress(hKernel, 'OpenThread');\n{$ENDIF !FPC}\nend;\n{ The OpenThread function does not exist on OS version < Win XP }\nOpenThreadExist := (@OpenThread <> nil);\nInitInternalFuncs();\n\nfinalization\n\nif (FreeKernel) and (hKernel > 0) then\n  FreeLibrary(hKernel);\nFreeInternalFuncs();\nif Assigned(FLock) then\n  FreeAndNil(FLock);\n\nend.\n"
  },
  {
    "path": "Source/DDetoursDefs.inc",
    "content": "{.$DEFINE HOOK_INTERNAL_FUNCTIONS}   // hook internal functions.\n\n{$IFDEF FPC}\n  {$ASMMODE INTEL}\n{$ELSE !FPC}\n\n{$T-}\n\n{$IF CompilerVersion >= 17.0}\n  {$DEFINE DELPHI_2005_UP}\n{$IFEND}\n\n{$IF CompilerVersion >= 18.5}\n  {$DEFINE DELPHI_2007_UP}\n{$IFEND}\n\n{$IF CompilerVersion >= 20}\n  {$DEFINE DELPHI_2009_UP}\n{$IFEND}\n\n{$IF CompilerVersion >= 21}\n  {$DEFINE DELPHI_2010_UP}\n{$IFEND}\n\n{$IF CompilerVersion >= 22}\n  {$DEFINE DELPHI_XE_UP}\n{$IFEND}\n\n{$IF CompilerVersion >= 23}\n  {$DEFINE DELPHI_XE2_UP}\n{$IFEND}\n\n{$IF CompilerVersion >= 33}\n  {$DEFINE DELPHI_RIO_UP}\n{$IFEND}\n\n{$IFDEF DELPHI_2005_UP}\n  {$DEFINE SUPPORTS_INLINE}\n{$ENDIF}\n\n{$IFDEF DELPHI_XE2_UP}\n  {$DEFINE SUPPORTS_RTTI}\n  {$DEFINE SUPPORTS_GENERICS}\n  {$DEFINE RENAMED_NAMESPACE}\n{$ENDIF}\n\n{$ENDIF FPC}\n\n"
  },
  {
    "path": "Source/InstDecode.pas",
    "content": "// **************************************************************************************************\n// x86 Instruction Decode Library\n// Unit InstDecode\n// https://github.com/MahdiSafsafi/DDetours\n//\n// This Source Code Form is subject to the terms of the Mozilla \n// Public License, v. 2.0. If a copy of the MPL was not distributed \n// with this file, You can obtain one at\n// https://mozilla.org/MPL/2.0/.\n// **************************************************************************************************\n\n{ ===============================> CHANGE LOG <======================================================\n  ==>  Jun, 7, 2020:\n  +Added support for older Delphi version (D7+).\n  +Added support for FPC.\n  +Fixed some bug related to displacement.\n  \n  ==>  Dec 27,2014 , Mahdi Safsafi :\n  +BugFix : IN/INS/OUT/OUTS instructions decoding.\n  +BugFix : MOV with offset instructions decoding.\n\n  ==> Version 2:\n  +Updated opcodes map .\n  +Added support to three byte escape Table\n  +Added support to vex decoding (vex three & two byte).\n  +Added support to groups opcodes instructions.\n  +Added support to decode invalid opcode .\n  +Added support to 16-bits ModRm .\n  +Added support to handling errors.\n  +Added support for mandatory prefixes.\n  +Improve Decoding Process .=> Very faster than the old one !\n  +Reduce memory usage .\n  +Removing inused fields.\n  +Better support for REX prefix.\n  +Reduce OpCodesTable data size (the old : 8670 bytes => the new one : 1020 bytes !)\n  +BugFix : FPU instructions length.\n  +BugFix : Instructions that use two immediat .\n  +BugFix : Invalid instructions .\n  +BugFix : Invalid instructions for some mandatory prefixes.\n  +Many Bug Fix.\n\n  ====================================================================================================== }\n\nunit InstDecode;\n\n{$IFDEF FPC}\n{$MODE DELPHI}\n{$HINTS OFF}\n{$WARN 4056 OFF}\n{$WARN 4082 OFF}\n{$ENDIF FPC}\n\ninterface\n\n{$I DDetoursDefs.inc}\n\nuses\n  SysUtils,\n  LegacyTypes;\n\nconst\n  { CPUX }\n  CPUX32 = $00; { x86-32 }\n  CPUX64 = $01; { x86-64 }\n  CPUX = {$IFDEF CPUX64}CPUX64 {$ELSE}CPUX32 {$ENDIF};\n\n  { Address Mode }\n  am16 = $01; { 16-bit addressing mode }\n  am32 = $02; { 32-bit addressing mode }\n  am64 = $03; { 64-bit addressing mode }\n  { Default Addressing Mode Depending on CPUX (32/64)bit }\n  DefAddressMode: array [0 .. 1] of Byte = (am32, am64);\n  { Used to select Addressing Mode when Address Mode Prefix is used ! }\n  AddressMode: array [0 .. 1] of Byte = (am16, am32);\n\n  { Tables }\n  tbOneByte = $01; { One Byte OpCodes Table }\n  tbTwoByte = $02; { Two Byte OpCodes Table }\n  tbThreeByte = $03; { Three Byte OpCodes Table }\n  tbFPU = $04; { FPU OpCodes Table }\n\n  { Prefixs }\n  Prf_Seg_CS = $01;\n  Prf_Seg_DS = $02;\n  Prf_Seg_ES = $04;\n  Prf_Seg_GS = $08;\n  Prf_Seg_FS = $10;\n  Prf_Seg_SS = $20;\n  Prf_OpSize = $40;\n  Prf_AddrSize = $80;\n  Prf_Lock = $100;\n  Prf_Repe = $200;\n  Prf_Repne = $400;\n  Prf_Rex = $800;\n  Prf_VEX = $1000;\n  Prf_Vex2 = Prf_VEX or $2000;\n  Prf_Vex3 = Prf_VEX or $4000;\n\n  { Segment Registers }\n  Seg_CS = $01;\n  Seg_DS = $02;\n  Seg_ES = $03;\n  Seg_GS = $04;\n  Seg_FS = $05;\n  Seg_SS = $06;\n\n  { OpSize }\n  ops8bits = $01;\n  ops16bits = $02;\n  ops32bits = $04;\n  ops48bits = $06;\n  ops64bits = $08;\n  ops128bits = $10;\n  ops256bits = $20;\n  ops512bits = $40;\n\n  { OpType }\n  otNone = $00;\n  otRET = $01; { RET Instruction }\n  otCALL = $02; { CALL Instruction }\n  otJMP = $04; { JMP Instruction }\n  otJ = $08;\n  otJcc = $10; { Conditional JUMP Instruction }\n\n  { OpKind }\n  kGrp = $01;\n  // kFPU = $02; Use OpTable !\n\n  { Options }\n  DecodeVex = $01;\n\n  { ModRm Flags }\n  mfUsed = $80; { ModRm Used }\n\n  { Sib Flags }\n  sfUsed = $01; { Sib Used }\n\n  { Displacement Flags }\n  dfUsed = $01; { Disp Used }\n  dfRip = $02; { RIP Disp }\n  dfSigned = $04; { Displacement can be signed ! }\n  dfDispOnly = $08; { Displacement Only without registers ! }\n  dfOffset = $10; { Offset coded after the opcode. }\n\n  { Immediat Flags }\n  imfUsed = $01; { Imm Used }\n\n  { Branch Flags }\n  bfUsed = $01; { JUMP/CALL Used }\n  bfRel = $02; { Relative Branch }\n  bfAbs = $04; { Absolute Branch }\n  bfIndirect = $08; { Indirect Branch }\n  bfReg = $10;\n  bfFar = bfAbs or $20; { Far Branch }\n  bfRip = $40;\n\n  { Operand Flags }\n  opdD64 = $01;\n  opdF64 = $02;\n  opdDf64 = $03;\n  opdDv64 = $04;\n\n  { Options }\n  UseVA = $01;\n\n  { General Purpose Registers }\n  rEAX = $00;\n  rECX = $01;\n  rEDX = $02;\n  rEBX = $03;\n  rESP = $04;\n  rEBP = $05;\n  rESI = $06;\n  rEDI = $07;\n\n  { Error }\n  NO_ERROR = $00;\n  INVALID_CPUX = $01;\n  INVALID_ADDRESS = $02;\n  INVALID_INSTRUCTION_LENGTH = $04;\n  ERROR_DISP_SIZE = $08;\n  ERROR_IMM_SIZE = $10;\n  ERROR_VEX_ESCAPE = $20;\n  INVALID_GROUP_OPCODE = $40;\n\n  UnknownErrorStr = 'Unknown Error';\n  InstErrorsStr: array [0 .. 7] of String = (\n    { NO_ERROR }\n    'No error',\n    { INVALID_CPUX }\n    'Invalid cpux',\n    { INVALID_ADDRESS }\n    'Invalid address',\n    { INVALID_INSTRUCTION_LENGTH }\n    'Invalid instruction length',\n    { ERROR_DISP_SIZE }\n    'Invalid displacement size',\n    { ERROR_IMM_SIZE }\n    'Invalid immediat size',\n    { ERROR_VEX_ESCAPE }\n    'Invalid vex mmmmm field',\n    { INVALID_GROUP_OPCODE }\n    'Invalid group opcode');\n\n  _vex3_ = $03;\n  _opcode_ = $01;\n  _modrm_ = $01;\n  _sib_ = $01;\n  _disp32_ = $04;\n  _imm32_ = $04;\n  _imm64_ = $08;\n  { Intel define instruction length as a 15 bytes !\n    However , it's possible to incode instructions\n    that exceed the defined length !\n  }\n  MAX_INST_LENGTH_X32 = _vex3_ + _opcode_ + _modrm_ + _sib_ + _disp32_ + _imm32_;\n  MAX_INST_LENGTH_X64 = _vex3_ + _opcode_ + _modrm_ + _sib_ + _disp32_ + _imm64_;\n  CPUX_TO_INST_LENGTH: array [0 .. 1] of ShortInt = (MAX_INST_LENGTH_X32, MAX_INST_LENGTH_X64);\n{$IFDEF CPUX64}\n  MAX_INST_LENGTH_N = MAX_INST_LENGTH_X64;\n{$ELSE !CPUX64}\n  MAX_INST_LENGTH_N = MAX_INST_LENGTH_X32;\n{$ENDIF CPUX64}\n\nvar\n  { Raise Exception When Error Occurs ! }\n  RaiseExceptionOnError: Boolean = True;\n\ntype\n  InstException = class(Exception);\n\n  TModRM = record\n    iMod: Byte; { ModRm.Mod Field }\n    Reg: Byte; { ModRm.Reg Field }\n    Rm: Byte; { ModRm.Rm Field }\n    Value: Byte; { ModRm Value }\n    { ModRm.Flags => See ModRmFlagsTable.inc }\n    Flags: Byte;\n  end;\n\n  PModRM = ^TModRM;\n  LPModRM = PModRM;\n\n  TSib = record\n    Scale: Byte; { SIB.Scale Field }\n    Index: Byte; { Register Index }\n    Base: Byte; { Register Base }\n    Value: Byte; { SIB Value }\n    Flags: Byte; { SIB Flags }\n  end;\n\n  PSib = ^TSib;\n  LPSib = PSib;\n\n  TImmediat = record\n    Size: Byte; { Size of Immediat => opsxxxbits }\n    Value: Int64; { Immediat Value }\n    Flags: Byte; { Sets of imfxxx }\n  end;\n\n  PImmediat = ^TImmediat;\n\n  TDisplacement = record\n    Size: Byte; { Size of Displacement => opsxxxbits }\n    Value: Int64; { Displacement Value }\n    Flags: Byte; { Sets of dfxxx }\n  end;\n\n  PDisplacement = ^TDisplacement;\n\n  TBranch = record\n    Size: Byte;\n    Value: Int64;\n    Target: PByte; { Destination Address }\n    Falgs: Byte; { Sets of bfxxx }\n  end;\n\n  PBranch = ^TBranch;\n\n  TRex = record\n    R: Boolean; { REX.R Field }\n    X: Boolean; { REX.X Field }\n    B: Boolean; { REX.B Field }\n    W: Boolean; { REX.W Field }\n    Value: Byte; { REX Value = [$40..$4F] }\n  end;\n\n  PRex = ^TRex;\n\n  TVex = record\n    {\n      ==================> N.B <==================\n      1 => ALL FIELD ARE IN NO INVERTED FORM !\n      2 => VEX.[R,X,B & W] ARE ACCESSIBLE THROUGH REX FIELD !\n\n    }\n    vvvv: Byte; { VEX.vvvv ==> Vector Register }\n    L: Boolean; { VEX.L ==> You should use VL instead ! }\n    PP: Byte; { VEX.PP ==> Implied Mandatory Prefixes }\n    mmmmm: Byte; { VEX.mmmmm ==> Implied Escape }\n    VL: Byte; { Vector Length }\n  end;\n\n  PVex = ^TVex;\n\n  TInternalData = record\n    MndPrf: Byte; { Mandatory Prefix }\n    zOpSize: Byte; { word or dword depending on opsize prefix ! }\n    vOpSize: Byte; { word or dword or qword depending on opsize & REX prefix ! }\n  end;\n\n  PInternalData = ^TInternalData;\n\n  TInstruction = record\n    Archi: Byte; { CPUX32 or CPUX64 ! }\n    AddrMode: Byte; { Address Mode }\n    Addr: PByte;\n    VirtualAddr: PByte;\n    NextInst: PByte; { Pointer to the Next Instruction }\n    OpCode: Byte; { OpCode Value }\n    OpType: Byte;\n    OpKind: Byte;\n    OpTable: Byte; { tbOneByte,tbTwoByte,... }\n    OperandFlags: Byte;\n    Prefixes: Word; { Sets of Prf_xxx }\n    ModRm: TModRM;\n    Sib: TSib;\n    Disp: TDisplacement;\n    Imm: TImmediat; { Primary Immediat }\n    ImmEx: TImmediat; { Secondary Immediat if used ! }\n    Branch: TBranch; { JMP & CALL }\n    SegReg: Byte; { Segment Register }\n    Rex: TRex;\n    Vex: TVex;\n    LID: TInternalData; { Internal Data }\n    Errors: Byte;\n    InstSize: Integer;\n    Options: Byte;\n    UserTag: NativeInt;\n  end;\n\n  PInstruction = ^TInstruction;\n\n  TDecoderProc = procedure(PInst: PInstruction);\n\nfunction DecodeInst(PInst: PInstruction): Integer;\n\n{ Useful ModRm Routines }\nfunction GetModRm_Mod(const Value: Byte): Byte; {$IFDEF MustInline}inline; {$ENDIF}\nfunction GetModRm_Reg(const Value: Byte): Byte; {$IFDEF MustInline}inline; {$ENDIF}\nfunction GetModRm_Rm(const Value: Byte): Byte; {$IFDEF MustInline}inline; {$ENDIF}\n{ Useful Sib Routines }\nfunction GetSib_Base(const Value: Byte): Byte; {$IFDEF MustInline}inline; {$ENDIF}\nfunction GetSib_Index(const Value: Byte): Byte; {$IFDEF MustInline}inline; {$ENDIF}\nfunction GetSib_Scale(const Value: Byte): Byte; {$IFDEF MustInline}inline; {$ENDIF}\nfunction IsSibBaseRegValid(PInst: PInstruction): Boolean; {$IFDEF MustInline}inline; {$ENDIF}\n\nimplementation\n\n{$I OpCodesTables.inc}\n{$I ModRmFlagsTables.inc}\n{ ================================== 00 ================================== }\nprocedure Decode_InvalidOpCode(PInst: PInstruction); forward;\n{ ================================== 01 ================================== }\nprocedure Decode_NA_ModRm(PInst: PInstruction); forward;\n{ ================================== 02 ================================== }\nprocedure Decode_NA_Ib(PInst: PInstruction); forward;\n{ ================================== 03 ================================== }\nprocedure Decode_NA_Iz(PInst: PInstruction); forward;\n{ ================================== 04 ================================== }\nprocedure Decode_NA_I64(PInst: PInstruction); forward;\n{ ================================== 05 ================================== }\nprocedure Decode_Escape_2_Byte(PInst: PInstruction); forward;\n{ ================================== 06 ================================== }\nprocedure Decode_ES_Prefix(PInst: PInstruction); forward;\n{ ================================== 07 ================================== }\nprocedure Decode_CS_Prefix(PInst: PInstruction); forward;\n{ ================================== 08 ================================== }\nprocedure Decode_SS_Prefix(PInst: PInstruction); forward;\n{ ================================== 09 ================================== }\nprocedure Decode_DS_Prefix(PInst: PInstruction); forward;\n{ ================================== 10 ================================== }\nprocedure Decode_REX_Prefix(PInst: PInstruction); forward;\n{ ================================== 11 ================================== }\nprocedure Decode_NA_D64(PInst: PInstruction); forward;\n{ ================================== 12 ================================== }\nprocedure Decode_NA_ModRm_I64(PInst: PInstruction); forward;\n{ ================================== 13 ================================== }\nprocedure Decode_FS_Prefix(PInst: PInstruction); forward;\n{ ================================== 14 ================================== }\nprocedure Decode_GS_Prefix(PInst: PInstruction); forward;\n{ ================================== 15 ================================== }\nprocedure Decode_OPSIZE_Prefix(PInst: PInstruction); forward;\n{ ================================== 16 ================================== }\nprocedure Decode_ADSIZE_Prefix(PInst: PInstruction); forward;\n{ ================================== 17 ================================== }\nprocedure Decode_NA_Iz_D64(PInst: PInstruction); forward;\n{ ================================== 18 ================================== }\nprocedure Decode_NA_ModRm_Iz(PInst: PInstruction); forward;\n{ ================================== 19 ================================== }\nprocedure Decode_NA_Ib_D64(PInst: PInstruction); forward;\n{ ================================== 20 ================================== }\nprocedure Decode_NA_ModRm_Ib(PInst: PInstruction); forward;\n{ ================================== 21 ================================== }\nprocedure Decode_NA(PInst: PInstruction); forward;\n{ ================================== 22 ================================== }\nprocedure Decode_NA_Jb_Df64(PInst: PInstruction); forward;\n{ ================================== 23 ================================== }\nprocedure Decode_Group_1(PInst: PInstruction); forward;\n{ ================================== 24 ================================== }\nprocedure Decode_Group_1A(PInst: PInstruction); forward;\n{ ================================== 25 ================================== }\nprocedure Decode_NA_CALL_Ap_I64(PInst: PInstruction); forward;\n{ ================================== 26 ================================== }\nprocedure Decode_NA_OfstV(PInst: PInstruction); forward;\n{ ================================== 27 ================================== }\nprocedure Decode_NA_Iv(PInst: PInstruction); forward;\n{ ================================== 28 ================================== }\nprocedure Decode_Group_2(PInst: PInstruction); forward;\n{ ================================== 29 ================================== }\nprocedure Decode_NA_RET_Iw_Df64(PInst: PInstruction); forward;\n{ ================================== 30 ================================== }\nprocedure Decode_NA_RET_Df64(PInst: PInstruction); forward;\n{ ================================== 31 ================================== }\nprocedure Decode_VEX3_Prefix(PInst: PInstruction); forward;\n{ ================================== 32 ================================== }\nprocedure Decode_VEX2_Prefix(PInst: PInstruction); forward;\n{ ================================== 33 ================================== }\nprocedure Decode_Group_11(PInst: PInstruction); forward;\n{ ================================== 34 ================================== }\nprocedure Decode_NA_Iw_Ib_D64(PInst: PInstruction); forward;\n{ ================================== 35 ================================== }\nprocedure Decode_NA_RET_Iw(PInst: PInstruction); forward;\n{ ================================== 36 ================================== }\nprocedure Decode_NA_RET(PInst: PInstruction); forward;\n{ ================================== 37 ================================== }\nprocedure Decode_NA_Ib_I64(PInst: PInstruction); forward;\n{ ================================== 38 ================================== }\nprocedure Decode_Escape_FPU_D8(PInst: PInstruction); forward;\n{ ================================== 39 ================================== }\nprocedure Decode_Escape_FPU_D9(PInst: PInstruction); forward;\n{ ================================== 40 ================================== }\nprocedure Decode_Escape_FPU_DA(PInst: PInstruction); forward;\n{ ================================== 41 ================================== }\nprocedure Decode_Escape_FPU_DB(PInst: PInstruction); forward;\n{ ================================== 42 ================================== }\nprocedure Decode_Escape_FPU_DC(PInst: PInstruction); forward;\n{ ================================== 43 ================================== }\nprocedure Decode_Escape_FPU_DD(PInst: PInstruction); forward;\n{ ================================== 44 ================================== }\nprocedure Decode_Escape_FPU_DE(PInst: PInstruction); forward;\n{ ================================== 45 ================================== }\nprocedure Decode_Escape_FPU_DF(PInst: PInstruction); forward;\n{ ================================== 46 ================================== }\nprocedure Decode_NA_CALL_Jz_Df64(PInst: PInstruction); forward;\n{ ================================== 47 ================================== }\nprocedure Decode_NA_JMP_Jz_Df64(PInst: PInstruction); forward;\n{ ================================== 48 ================================== }\nprocedure Decode_NA_JMP_Ap_I64(PInst: PInstruction); forward;\n{ ================================== 49 ================================== }\nprocedure Decode_NA_JMP_Jb_Df64(PInst: PInstruction); forward;\n{ ================================== 50 ================================== }\nprocedure Decode_LOCK_Prefix(PInst: PInstruction); forward;\n{ ================================== 51 ================================== }\nprocedure Decode_REPNE_Prefix(PInst: PInstruction); forward;\n{ ================================== 52 ================================== }\nprocedure Decode_REPE_Prefix(PInst: PInstruction); forward;\n{ ================================== 53 ================================== }\nprocedure Decode_Group_3(PInst: PInstruction); forward;\n{ ================================== 54 ================================== }\nprocedure Decode_Group_4_INC_DEC(PInst: PInstruction); forward;\n{ ================================== 55 ================================== }\nprocedure Decode_Group_5_INC_DEC(PInst: PInstruction); forward;\n{ ================================== 56 ================================== }\nprocedure Decode_Group_6(PInst: PInstruction); forward;\n{ ================================== 57 ================================== }\nprocedure Decode_Group_7(PInst: PInstruction); forward;\n{ ================================== 58 ================================== }\nprocedure Decode_NA_CALL(PInst: PInstruction); forward;\n{ ================================== 59 ================================== }\nprocedure Decode_NA_66_F2_F3_ModRm(PInst: PInstruction); forward;\n{ ================================== 60 ================================== }\nprocedure Decode_NA_66_ModRm(PInst: PInstruction); forward;\n{ ================================== 61 ================================== }\nprocedure Decode_NA_66_F3_ModRm(PInst: PInstruction); forward;\n{ ================================== 62 ================================== }\nprocedure Decode_Group_16(PInst: PInstruction); forward;\n{ ================================== 63 ================================== }\nprocedure Decode_NA_ModRm_F64(PInst: PInstruction); forward;\n{ ================================== 64 ================================== }\nprocedure Decode_Escape_3_Byte(PInst: PInstruction); forward;\n{ ================================== 65 ================================== }\nprocedure Decode_NA_F3_ModRm(PInst: PInstruction); forward;\n{ ================================== 66 ================================== }\nprocedure Decode_66_ModRm(PInst: PInstruction); forward;\n{ ================================== 67 ================================== }\nprocedure Decode_NA_66_F2_F3_ModRm_Ib(PInst: PInstruction); forward;\n{ ================================== 68 ================================== }\nprocedure Decode_Group_12(PInst: PInstruction); forward;\n{ ================================== 69 ================================== }\nprocedure Decode_Group_13(PInst: PInstruction); forward;\n{ ================================== 70 ================================== }\nprocedure Decode_Group_14(PInst: PInstruction); forward;\n{ ================================== 71 ================================== }\nprocedure Decode_66_F2_ModRm(PInst: PInstruction); forward;\n{ ================================== 72 ================================== }\nprocedure Decode_NA_Jz_Df64(PInst: PInstruction); forward;\n{ ================================== 73 ================================== }\nprocedure Decode_Group_15(PInst: PInstruction); forward;\n{ ================================== 74 ================================== }\nprocedure Decode_F3_ModRm(PInst: PInstruction); forward;\n{ ================================== 75 ================================== }\nprocedure Decode_Group_10_UD2(PInst: PInstruction); forward;\n{ ================================== 76 ================================== }\nprocedure Decode_Group_8(PInst: PInstruction); forward;\n{ ================================== 77 ================================== }\nprocedure Decode_NA_66_ModRm_Ib(PInst: PInstruction); forward;\n{ ================================== 78 ================================== }\nprocedure Decode_Group_9(PInst: PInstruction); forward;\n{ ================================== 79 ================================== }\nprocedure Decode_66_F2_F3_ModRm(PInst: PInstruction); forward;\n{ ================================== 80 ================================== }\nprocedure Decode_F2_ModRm(PInst: PInstruction); forward;\n{ ================================== 81 ================================== }\nprocedure Decode_SP_T38_F0_F7(PInst: PInstruction); forward;\n{ ================================== 82 ================================== }\nprocedure Decode_66_ModRm_Ib(PInst: PInstruction); forward;\n{ ================================== 83 ================================== }\nprocedure Decode_F2_ModRm_Ib(PInst: PInstruction); forward;\n\nprocedure JumpError(PInst: PInstruction); forward;\nprocedure JumpToTableTwoByte(PInst: PInstruction); forward;\nprocedure JumpToTableThreeByte_38(PInst: PInstruction); forward;\nprocedure JumpToTableThreeByte_3A(PInst: PInstruction); forward;\n\nprocedure Decode_CALL_ModRm(PInst: PInstruction); forward;\nprocedure Decode_JMP_ModRm(PInst: PInstruction); forward;\nprocedure Decode_CALL_Mp(PInst: PInstruction); forward;\nprocedure Decode_JMP_Mp(PInst: PInstruction); forward;\n\nconst\n\n  { Convert PP To Mandatory Prefixes ! }\n  PPToMndPrf: array [0 .. 3] of Byte = ($00, $66, $F3, $F2);\n\n  { Convert LL To OpSize ! }\n  LLToOpSize: array [0 .. 3] of Word = (ops128bits, ops256bits, ops512bits, 0);\n\n  { Call escaping procedure ! }\n  mmmmmToEscProc: array [0 .. 4] of TDecoderProc = ( //\n    JumpError, { }\n    JumpToTableTwoByte, { 00001: implied 0F leading opcode byte }\n    JumpToTableThreeByte_38, { 00010: implied 0F 38 leading opcode bytes }\n    JumpToTableThreeByte_3A, { 00011: implied 0F 3A leading opcode bytes }\n    JumpError { }\n    );\n\n  DecoderProcTable: array [0 .. $54 - 1] of TDecoderProc = ( //\n    { 00 } Decode_InvalidOpCode,\n    { 01 } Decode_NA_ModRm,\n    { 02 } Decode_NA_Ib,\n    { 03 } Decode_NA_Iz,\n    { 04 } Decode_NA_I64,\n    { 05 } Decode_Escape_2_Byte,\n    { 06 } Decode_ES_Prefix,\n    { 07 } Decode_CS_Prefix,\n    { 08 } Decode_SS_Prefix,\n    { 09 } Decode_DS_Prefix,\n    { 10 } Decode_REX_Prefix,\n    { 11 } Decode_NA_D64,\n    { 12 } Decode_NA_ModRm_I64,\n    { 13 } Decode_FS_Prefix,\n    { 14 } Decode_GS_Prefix,\n    { 15 } Decode_OPSIZE_Prefix,\n    { 16 } Decode_ADSIZE_Prefix,\n    { 17 } Decode_NA_Iz_D64,\n    { 18 } Decode_NA_ModRm_Iz,\n    { 19 } Decode_NA_Ib_D64,\n    { 20 } Decode_NA_ModRm_Ib,\n    { 21 } Decode_NA,\n    { 22 } Decode_NA_Jb_Df64,\n    { 23 } Decode_Group_1,\n    { 24 } Decode_Group_1A,\n    { 25 } Decode_NA_CALL_Ap_I64,\n    { 26 } Decode_NA_OfstV,\n    { 27 } Decode_NA_Iv,\n    { 28 } Decode_Group_2,\n    { 29 } Decode_NA_RET_Iw_Df64,\n    { 30 } Decode_NA_RET_Df64,\n    { 31 } Decode_VEX3_Prefix,\n    { 32 } Decode_VEX2_Prefix,\n    { 33 } Decode_Group_11,\n    { 34 } Decode_NA_Iw_Ib_D64,\n    { 35 } Decode_NA_RET_Iw,\n    { 36 } Decode_NA_RET,\n    { 37 } Decode_NA_Ib_I64,\n    { 38 } Decode_Escape_FPU_D8,\n    { 39 } Decode_Escape_FPU_D9,\n    { 40 } Decode_Escape_FPU_DA,\n    { 41 } Decode_Escape_FPU_DB,\n    { 42 } Decode_Escape_FPU_DC,\n    { 43 } Decode_Escape_FPU_DD,\n    { 44 } Decode_Escape_FPU_DE,\n    { 45 } Decode_Escape_FPU_DF,\n    { 46 } Decode_NA_CALL_Jz_Df64,\n    { 47 } Decode_NA_JMP_Jz_Df64,\n    { 48 } Decode_NA_JMP_Ap_I64,\n    { 49 } Decode_NA_JMP_Jb_Df64,\n    { 50 } Decode_LOCK_Prefix,\n    { 51 } Decode_REPNE_Prefix,\n    { 52 } Decode_REPE_Prefix,\n    { 53 } Decode_Group_3,\n    { 54 } Decode_Group_4_INC_DEC,\n    { 55 } Decode_Group_5_INC_DEC,\n    { 56 } Decode_Group_6,\n    { 57 } Decode_Group_7,\n    { 58 } Decode_NA_CALL,\n    { 59 } Decode_NA_66_F2_F3_ModRm,\n    { 60 } Decode_NA_66_ModRm,\n    { 61 } Decode_NA_66_F3_ModRm,\n    { 62 } Decode_Group_16,\n    { 63 } Decode_NA_ModRm_F64,\n    { 64 } Decode_Escape_3_Byte,\n    { 65 } Decode_NA_F3_ModRm,\n    { 66 } Decode_66_ModRm,\n    { 67 } Decode_NA_66_F2_F3_ModRm_Ib,\n    { 68 } Decode_Group_12,\n    { 69 } Decode_Group_13,\n    { 70 } Decode_Group_14,\n    { 71 } Decode_66_F2_ModRm,\n    { 72 } Decode_NA_Jz_Df64,\n    { 73 } Decode_Group_15,\n    { 74 } Decode_F3_ModRm,\n    { 75 } Decode_Group_10_UD2,\n    { 76 } Decode_Group_8,\n    { 77 } Decode_NA_66_ModRm_Ib,\n    { 78 } Decode_Group_9,\n    { 79 } Decode_66_F2_F3_ModRm,\n    { 80 } Decode_F2_ModRm,\n    { 81 } Decode_SP_T38_F0_F7,\n    { 82 } Decode_66_ModRm_Ib,\n    { 83 } Decode_F2_ModRm_Ib);\n  { .$REGION 'COMMON' }\n  { ========================== COMMON =============================== }\n\nprocedure SetInstError(PInst: PInstruction; Error: Byte);\nvar\n  ErrStr: String;\nbegin\n  ErrStr := EmptyStr;\n  if Error = NO_ERROR then\n  begin\n    { Clear Errors ! }\n    PInst^.Errors := NO_ERROR;\n    Exit;\n  end;\n  PInst^.Errors := PInst^.Errors or Error;\n\n  if RaiseExceptionOnError then\n  begin\n    if (Error > 0) and (Error < Length(InstErrorsStr)) then\n      ErrStr := InstErrorsStr[Error]\n    else\n      ErrStr := UnknownErrorStr;\n    raise InstException.Create(Format('Error %d : %s.', [Error, ErrStr]));\n  end;\nend;\n\nfunction GetModRm_Mod(const Value: Byte): Byte;\nbegin\n  Result := Value shr 6;\nend;\n\nfunction GetModRm_Reg(const Value: Byte): Byte;\nbegin\n  Result := (Value and $38) shr $03;\nend;\n\nfunction GetModRm_Rm(const Value: Byte): Byte;\nbegin\n  Result := Value and 7;\nend;\n\nfunction GetSib_Base(const Value: Byte): Byte;\nbegin\n  Result := Value and 7;\nend;\n\nfunction GetSib_Index(const Value: Byte): Byte;\nbegin\n  Result := (Value and $38) shr $03;\nend;\n\nfunction GetSib_Scale(const Value: Byte): Byte;\nbegin\n  Result := (1 shl (Value shr 6));\nend;\n\nfunction IsSibBaseRegValid(PInst: PInstruction): Boolean;\nbegin\n  Result := True;\n  if PInst^.Sib.Flags and sfUsed <> 0 then\n    Result := not((PInst^.ModRm.iMod = 0) and (PInst^.Sib.Base = 5));\nend;\n\nprocedure SetOpCode(PInst: PInstruction); {$IFDEF MustInline}inline; {$ENDIF}\nbegin\n  PInst^.OpCode := PInst^.NextInst^;\n  Inc(PInst^.NextInst);\nend;\n\nprocedure SetGroup(PInst: PInstruction); {$IFDEF MustInline}inline; {$ENDIF}\nbegin\n  PInst^.OpKind := kGrp;\nend;\n\nprocedure ForceOpSize(PInst: PInstruction); {$IFDEF MustInline}inline; {$ENDIF}\nbegin\n  if PInst^.Archi = CPUX32 then\n    Exit;\n  PInst^.LID.vOpSize := ops64bits;\nend;\n\nprocedure DecodeSib(PInst: PInstruction); {$IFDEF MustInline}inline; {$ENDIF}\nvar\n  PSib: LPSib;\nbegin\n  PSib := @PInst^.Sib;\n  PSib.Flags := sfUsed;\n  PSib.Value := PInst^.NextInst^;\n  PSib.Base := GetSib_Base(PSib.Value);\n  PSib.Index := GetSib_Index(PSib.Value);\n  PSib.Scale := GetSib_Scale(PSib.Value);\n  Inc(PInst^.NextInst); // Skip SIB !\nend;\n\nprocedure DecodeDisp(PInst: PInstruction);\nvar\n  Disp: Int64;\n  Size: Byte;\n  DispOnly: Boolean;\nbegin\n  Disp := $00;\n  Size := PInst^.Disp.Size;\n  PInst^.Disp.Flags := dfUsed;\n  DispOnly := (PInst^.ModRm.iMod = $00) and (PInst^.ModRm.Rm = $05);\n\n  case Size of\n    ops8bits:\n      Disp := (PInt8(PInst^.NextInst)^); // and $FF;\n    ops16bits:\n      Disp := (PInt16(PInst^.NextInst)^); // and $FFFF;\n    ops32bits:\n      begin\n        Disp := (PInt32(PInst^.NextInst)^); // and $FFFFFFFF;\n        if (PInst^.Archi = CPUX64) and DispOnly then\n          { RIP disp ! }\n          PInst^.Disp.Flags := PInst^.Disp.Flags or dfRip;\n      end;\n  else\n    SetInstError(PInst, ERROR_DISP_SIZE);\n  end;\n\n  if DispOnly then\n    PInst^.Disp.Flags := PInst^.Disp.Flags or dfDispOnly\n  else\n    PInst^.Disp.Flags := PInst^.Disp.Flags or dfSigned;\n\n  PInst^.Disp.Value := Disp;\n  Inc(PInst^.NextInst, Size) // Skip Disp !\nend;\n\nprocedure Decode_ModRm(PInst: PInstruction);\nvar\n  PModRM: LPModRM;\n  SibUsed: Boolean;\nconst\n  { Get Disp Size from ModRm . }\n  ModRMFlagsToDispSize: array [0 .. 4] of Byte = (0, ops8bits, ops16bits, 0, ops32bits);\nbegin\n  PModRM := @PInst^.ModRm;\n  PModRM.Value := PInst^.NextInst^;\n  PModRM.iMod := GetModRm_Mod(PModRM.Value);\n  PModRM.Reg := GetModRm_Reg(PModRM.Value);\n  PModRM.Rm := GetModRm_Rm(PModRM.Value);\n  PModRM.Flags := ModRMFlags[PInst^.AddrMode][PModRM.Value];\n\n  PInst^.Disp.Size := ModRMFlagsToDispSize[(PModRM.Flags shr 1) and 7];\n  Inc(PInst^.NextInst); // Skip ModRM !\n\n  SibUsed := (PModRM.Flags and $10 > 0); { SibUsed ! }\n\n  if SibUsed then\n  begin\n    DecodeSib(PInst);\n    { if the base is not valid ==> there is a disp32 .\n      But the disp can be 8bit ==> we need to check first\n      if the disp does not exist !\n    }\n    if (PInst^.Disp.Size = 0) and (not IsSibBaseRegValid(PInst)) then\n      PInst^.Disp.Size := ops32bits;\n  end;\n\n  if PInst^.Disp.Size > 0 then\n    DecodeDisp(PInst);\n\n  { ModRm Exists ! }\n  PModRM.Flags := PModRM.Flags or mfUsed;\nend;\n\nprocedure Decode_Imm(PInst: PInstruction; immSize: Byte);\nvar\n  Imm: Int64;\n  PImm: PImmediat;\nbegin\n  Imm := $00;\n  case immSize of\n    ops8bits:\n      Imm := (PInt8(PInst^.NextInst)^);\n    ops16bits:\n      Imm := (PInt16(PInst^.NextInst)^);\n    ops32bits:\n      Imm := (PInt32(PInst^.NextInst)^);\n    ops64bits:\n      Imm := (PInt64(PInst^.NextInst)^);\n  else\n    SetInstError(PInst, ERROR_IMM_SIZE);\n  end;\n\n  {\n    If Imm field already used => get the extra Imm\n  }\n  if PInst^.Imm.Flags and imfUsed <> $00 then\n    PImm := @PInst^.ImmEx\n  else\n    PImm := @PInst^.Imm;\n\n  PImm.Flags := imfUsed;\n  PImm.Value := Imm;\n  PImm.Size := immSize;\n  Inc(PInst^.NextInst, immSize); // Skip Immediat !\nend;\n\nprocedure Decode_J(PInst: PInstruction; Size: Byte);\nvar\n  Value: Int64;\n  VA: PByte;\nbegin\n  Value := $00;\n  case Size of\n    ops8bits:\n      Value := (PInt8(PInst^.NextInst)^);\n    ops16bits:\n      Value := (PInt16(PInst^.NextInst)^);\n    ops32bits:\n      Value := (PInt32(PInst^.NextInst)^);\n    ops64bits:\n      Value := (PInt64(PInst^.NextInst)^);\n  end;\n  Inc(PInst^.NextInst, Size);\n  if PInst^.OpType = otNone then\n    PInst^.OpType := otJ;\n  if PInst^.OpCode in [$70 .. $8F] then\n    PInst^.OpType := otJ or otJcc;\n  if Assigned(PInst^.VirtualAddr) then\n    VA := PByte(NativeInt(PInst^.VirtualAddr) + NativeInt(NativeInt(PInst^.NextInst) - NativeInt(PInst^.Addr)))\n  else\n    VA := PInst^.NextInst;\n  PInst^.Branch.Size := Size;\n  PInst^.Branch.Falgs := bfUsed or bfRel;\n  PInst^.Branch.Value := Value;\n  PInst^.Branch.Target := PByte(NativeInt(VA) + Value);\nend;\n\nprocedure Decode_Branch_ModRm(PInst: PInstruction);\nvar\n  P: PByte;\n  VA: PByte;\nbegin\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\n  PInst^.Branch.Value := PInst^.Disp.Value;\n  PInst^.Branch.Size := PInst^.Disp.Size;\n  PInst^.Branch.Falgs := bfUsed or bfIndirect or bfAbs;\n  if Assigned(PInst^.VirtualAddr) then\n    VA := PByte(NativeInt(PInst^.VirtualAddr) + (NativeInt(PInst^.NextInst) - NativeInt(PInst^.Addr)))\n  else\n    VA := PInst^.NextInst;\n  if (PInst^.ModRm.iMod = $00) and (PInst^.ModRm.Rm = $05) then\n  begin\n    { Memory = Displacement }\n    if PInst^.Archi = CPUX64 then\n    begin\n      if PInst^.Prefixes and Prf_AddrSize <> 0 then\n        { Displacement = EIP + Offset }\n        VA := PByte(UInt64(VA) and $FFFFFFFF);\n      { Displacement = RIP + Offset }\n      PInst^.Branch.Falgs := PInst^.Branch.Falgs or bfRip;\n      P := PByte(NativeInt(VA) + NativeInt(PInst^.Disp.Value));\n      { Memory 64-bits }\n      PInst^.Branch.Target := PByte(PUInt64(P)^);\n    end\n    else\n    begin\n      { No RIP }\n      P := PByte(UInt32(PInst^.Disp.Value));\n      if PInst^.Prefixes and Prf_OpSize <> 0 then\n        { Memory 16-bits }\n        PInst^.Branch.Target := PByte(PUInt16(P)^)\n      else\n        { Memory 32-bits }\n        PInst^.Branch.Target := PByte(PUInt32(P)^);\n    end;\n  end\n  else\n  begin\n    { Memory = Displacement + Register }\n    PInst^.Branch.Falgs := PInst^.Branch.Falgs or bfReg;\n    PInst^.Branch.Target := nil;\n  end;\nend;\n\nprocedure Decode_Ap(PInst: PInstruction);\nbegin\n  SetOpCode(PInst);\n  PInst^.Branch.Falgs := bfUsed or bfFar;\n  { We must clear the upper word ! }\n  PInst^.Branch.Value := PUInt64(PInst^.NextInst)^ and $FFFFFFFFFFFF;\n  PInst^.Branch.Size := ops48bits;\n  PInst^.Branch.Target := nil;\n  Inc(PInst^.NextInst, ops48bits);\nend;\n\nprocedure Decode_Mp(PInst: PInstruction);\nbegin\n  SetOpCode(PInst);\n  PInst^.Branch.Falgs := bfUsed or bfFar;\n  Decode_ModRm(PInst);\n  PInst^.Branch.Value := PInst^.Disp.Value;\n  PInst^.Branch.Size := PInst^.Disp.Size;\n  PInst^.Branch.Target := nil;\nend;\n\nprocedure Decode_InvalidOpCode(PInst: PInstruction); {$IFDEF MustInline}inline;\n{$ENDIF}\nbegin\n  SetOpCode(PInst);\nend;\n\nprocedure Decode_Invalid_Group(PInst: PInstruction); {$IFDEF MustInline}inline;\n{$ENDIF}\nbegin\n  SetOpCode(PInst);\n  Inc(PInst^.NextInst);\nend;\n\nprocedure Decode_Invalid_FPU(PInst: PInstruction); {$IFDEF MustInline}inline;\n{$ENDIF}\nbegin\n  SetOpCode(PInst);\n  Inc(PInst^.NextInst);\nend;\n\n{ .$ENDREGION }\n{ .$REGION 'PREFIXES' }\n{ ========================== PREFIXES =============================== }\n\nprocedure Decode_ES_Prefix(PInst: PInstruction);\nbegin\n  { ES Segment Override Prefix }\n  Inc(PInst^.NextInst);\n  PInst^.Prefixes := PInst^.Prefixes or Prf_Seg_ES;\n  PInst^.SegReg := Seg_ES;\n  DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_CS_Prefix(PInst: PInstruction);\nbegin\n  { CS Segment Override Prefix }\n  Inc(PInst^.NextInst);\n  PInst^.Prefixes := PInst^.Prefixes or Prf_Seg_CS;\n  PInst^.SegReg := Seg_CS;\n  DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_SS_Prefix(PInst: PInstruction);\nbegin\n  { SS Segment Override Prefix }\n  Inc(PInst^.NextInst);\n  PInst^.Prefixes := PInst^.Prefixes or Prf_Seg_SS;\n  PInst^.SegReg := Seg_SS;\n  DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_DS_Prefix(PInst: PInstruction);\nbegin\n  { DS Segment Override Prefix }\n  Inc(PInst^.NextInst);\n  PInst^.Prefixes := PInst^.Prefixes or Prf_Seg_DS;\n  PInst^.SegReg := Seg_DS;\n  DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_REX_Prefix(PInst: PInstruction);\nbegin\n  { REX Prefix valid only on PM64! }\n  if PInst^.Archi = CPUX32 then\n  begin\n    { INC/DEC REG }\n    Decode_NA(PInst);\n    Exit;\n  end;\n  PInst^.Prefixes := PInst^.Prefixes or Prf_Rex;\n  PInst^.Rex.Value := PInst^.NextInst^;\n  PInst^.Rex.B := (PInst^.Rex.Value and 1 <> 0);\n  PInst^.Rex.X := (PInst^.Rex.Value and 2 <> 0);\n  PInst^.Rex.R := (PInst^.Rex.Value and 4 <> 0);\n  PInst^.Rex.W := (PInst^.Rex.Value and 8 <> 0);\n\n  if PInst^.Rex.W then\n    PInst^.LID.vOpSize := ops64bits;\n\n  Inc(PInst^.NextInst); // Skip Rex .\n  DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_FS_Prefix(PInst: PInstruction);\nbegin\n  { FS Segment Override Prefix }\n  Inc(PInst^.NextInst);\n  PInst^.Prefixes := PInst^.Prefixes or Prf_Seg_FS;\n  PInst^.SegReg := Seg_FS;\n  DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_GS_Prefix(PInst: PInstruction);\nbegin\n  { GS Segment Override Prefix }\n  Inc(PInst^.NextInst);\n  PInst^.Prefixes := PInst^.Prefixes or Prf_Seg_GS;\n  PInst^.SegReg := Seg_GS;\n  DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_OPSIZE_Prefix(PInst: PInstruction);\nbegin\n  PInst^.Prefixes := PInst^.Prefixes or Prf_OpSize;\n  PInst^.LID.vOpSize := ops16bits;\n  PInst^.LID.zOpSize := ops16bits;\n  PInst^.LID.MndPrf := $66;\n  Inc(PInst^.NextInst);\n  DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_ADSIZE_Prefix(PInst: PInstruction);\nbegin\n  PInst^.Prefixes := PInst^.Prefixes or Prf_AddrSize;\n  Inc(PInst^.NextInst);\n  PInst^.AddrMode := AddressMode[PInst^.Archi];\n  DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_VEX3_Prefix(PInst: PInstruction);\nvar\n  P: Byte;\n  Q: PByte;\n  R, X: Boolean;\nbegin\n  if PInst^.Options and DecodeVex = 0 then\n  begin\n    Decode_NA_ModRm(PInst);\n    Exit;\n  end;\n  if PInst^.Archi = CPUX32 then\n  begin\n    Q := PInst^.NextInst;\n    Inc(Q);\n    R := (Q^ and $80 <> 0);\n    X := (Q^ and $40 <> 0);\n    {\n      if R & X are set ==> Vex prefix is valid !\n      otherwise the instruction is LES .\n    }\n    if not(R and X) then\n    begin\n      { LES instruction }\n      Decode_NA_ModRm(PInst);\n      Exit;\n    end;\n  end;\n\n  Inc(PInst^.NextInst); // Skip $C4 !\n  PInst^.Prefixes := PInst^.Prefixes or Prf_Vex3;\n  P := PInst^.NextInst^; // P0\n  PInst^.Rex.R := not(P and $80 <> 0);\n  PInst^.Rex.X := not(P and $40 <> 0);\n  PInst^.Rex.B := not(P and $20 <> 0);\n  PInst^.Vex.mmmmm := (P and $1F);\n  Inc(PInst^.NextInst); // Skip P0\n  P := PInst^.NextInst^; // P1\n  Inc(PInst^.NextInst); // Skip P1\n  PInst^.Rex.W := (P and $80 <> 0);\n  PInst^.Vex.vvvv := $0F - ((P and $78) shr 3);\n  PInst^.Vex.L := (P and 4 <> 0);\n  PInst^.Vex.PP := (P and 3);\n  PInst^.Vex.VL := LLToOpSize[Byte(PInst^.Vex.L)];\n  PInst^.LID.MndPrf := PPToMndPrf[PInst^.Vex.PP];\n  mmmmmToEscProc[PInst^.Vex.mmmmm](PInst);\nend;\n\nprocedure Decode_VEX2_Prefix(PInst: PInstruction);\nvar\n  P: Byte;\n  Q: PByte;\n  R: Boolean;\nbegin\n  if PInst^.Options and DecodeVex = 0 then\n  begin\n    Decode_NA_ModRm(PInst);\n    Exit;\n  end;\n  if PInst^.Archi = CPUX32 then\n  begin\n    Q := PInst^.NextInst;\n    Inc(Q);\n    R := (Q^ and $80 <> 0);\n    {\n      if R is set ==> Vex prefix is valid !\n      otherwise the instruction is LDS.\n    }\n    if not R then\n    begin\n      { LDS instruction }\n      Decode_NA_ModRm(PInst);\n      Exit;\n    end;\n  end;\n\n  Inc(PInst^.NextInst); // Skip $C5 !\n  PInst^.Prefixes := PInst^.Prefixes or Prf_Vex2;\n  P := PInst^.NextInst^;\n  PInst^.Rex.R := not(P and $80 <> 0);\n  PInst^.Vex.vvvv := $0F - ((P and $78) shr 3);\n  PInst^.Vex.L := (P and 4 <> 0);\n  PInst^.Vex.PP := (P and 3);\n  PInst^.Vex.VL := LLToOpSize[Byte(PInst^.Vex.L)];\n  PInst^.LID.MndPrf := PPToMndPrf[PInst^.Vex.PP];\n  Inc(PInst^.NextInst); // Skip P0 !\n  DecoderProcTable[TwoByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_LOCK_Prefix(PInst: PInstruction);\nbegin\n  PInst^.Prefixes := PInst^.Prefixes or Prf_Lock;\n  Inc(PInst^.NextInst);\n  DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_REPNE_Prefix(PInst: PInstruction);\nbegin\n  PInst^.Prefixes := PInst^.Prefixes or Prf_Repne;\n  PInst^.LID.MndPrf := $F2;\n  Inc(PInst^.NextInst);\n  DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_REPE_Prefix(PInst: PInstruction);\nbegin\n  PInst^.Prefixes := PInst^.Prefixes or Prf_Repe;\n  PInst^.LID.MndPrf := $F3;\n  Inc(PInst^.NextInst);\n  DecoderProcTable[OneByteTable[PInst^.NextInst^]](PInst);\nend;\n{ .$ENDREGION }\n{ .$REGION 'ESCAPE' }\n{ ========================== ESCAPE =============================== }\n\nprocedure JumpError(PInst: PInstruction);\nbegin\n  { Wrong Vex.mmmmm value ! }\n  SetInstError(PInst, ERROR_VEX_ESCAPE);\nend;\n\nprocedure JumpToTableTwoByte(PInst: PInstruction);\nbegin\n  { Implied $0F OpCode => Jump to table TwoByteTable }\n  PInst^.OpTable := tbTwoByte;\n  DecoderProcTable[TwoByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure JumpToTableThreeByte_38(PInst: PInstruction);\nbegin\n  { Implied $0F$38 OpCodes => Jump to table ThreeByteTable.38 }\n  PInst^.OpTable := tbThreeByte;\n  DecoderProcTable[ThreeByteTable38[PInst^.NextInst^]](PInst);\nend;\n\nprocedure JumpToTableThreeByte_3A(PInst: PInstruction);\nbegin\n  { Implied $0F$3A OpCodes => Jump to table ThreeByteTable.3A }\n  PInst^.OpTable := tbThreeByte;\n  DecoderProcTable[ThreeByteTable3A[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_Escape_2_Byte(PInst: PInstruction);\nbegin\n  { Two Byte OpCode Escape ! }\n  PInst^.OpTable := tbTwoByte;\n  Inc(PInst^.NextInst);\n  DecoderProcTable[TwoByteTable[PInst^.NextInst^]](PInst);\nend;\n\nprocedure Decode_Escape_3_Byte(PInst: PInstruction);\nvar\n  P: Byte;\nbegin\n  { Three Byte OpCode Escape ! }\n  PInst^.OpTable := tbThreeByte;\n  P := PInst^.NextInst^;\n  Inc(PInst^.NextInst);\n  if P = $38 then\n    DecoderProcTable[ThreeByteTable38[PInst^.NextInst^]](PInst)\n  else\n    DecoderProcTable[ThreeByteTable3A[PInst^.NextInst^]](PInst);\nend;\n\n{ .$ENDREGION }\n{ .$REGION 'FPU' }\n{ ========================== FPU =============================== }\n\nprocedure Decode_Escape_FPU_D8(PInst: PInstruction);\nbegin\n  { All OpCode are valid for $D8 ! }\n  PInst^.OpTable := tbFPU;\n  Decode_NA_ModRm(PInst);\nend;\n\nprocedure Decode_Escape_FPU_D9(PInst: PInstruction);\nvar\n  P: PByte;\n  ModRm: Byte;\n  Reg: Byte;\nbegin\n  PInst^.OpTable := tbFPU;\n  P := PInst^.NextInst;\n  Inc(P);\n  ModRm := P^;\n  Reg := GetModRm_Reg(ModRm);\n  if ModRm < $C0 then\n  begin\n    if Reg = $01 then\n    begin\n      Decode_Invalid_FPU(PInst);\n      Exit;\n    end;\n  end\n  else\n  begin\n    if ModRm in [$D1 .. $DF, $E2, $E3, $EF] then\n    begin\n      Decode_Invalid_FPU(PInst);\n      Exit;\n    end;\n  end;\n  Decode_NA_ModRm(PInst);\nend;\n\nprocedure Decode_Escape_FPU_DA(PInst: PInstruction);\nvar\n  P: PByte;\n  ModRm: Byte;\nbegin\n  PInst^.OpTable := tbFPU;\n  P := PInst^.NextInst;\n  Inc(P);\n  ModRm := P^;\n  if ModRm > $C0 then\n  begin\n    if ModRm in [$E0 .. $E8, $EA .. $EF, $F0 .. $FF] then\n    begin\n      Decode_Invalid_FPU(PInst);\n      Exit;\n    end;\n  end;\n  Decode_NA_ModRm(PInst);\nend;\n\nprocedure Decode_Escape_FPU_DB(PInst: PInstruction);\nvar\n  P: PByte;\n  ModRm: Byte;\n  Reg: Byte;\nbegin\n  PInst^.OpTable := tbFPU;\n  P := PInst^.NextInst;\n  Inc(P);\n  ModRm := P^;\n  Reg := GetModRm_Reg(ModRm);\n  if ModRm < $C0 then\n  begin\n    if (Reg = $04) or (Reg = $06) then\n    begin\n      Decode_Invalid_FPU(PInst);\n      Exit;\n    end;\n  end\n  else\n  begin\n    if ModRm in [$E0, $E1, $E4 .. $E7, $F8 .. $FF] then\n    begin\n      Decode_Invalid_FPU(PInst);\n      Exit;\n    end;\n  end;\n  Decode_NA_ModRm(PInst);\nend;\n\nprocedure Decode_Escape_FPU_DC(PInst: PInstruction);\nvar\n  P: PByte;\n  ModRm: Byte;\nbegin\n  PInst^.OpTable := tbFPU;\n  P := PInst^.NextInst;\n  Inc(P);\n  ModRm := P^;\n  if ModRm > $C0 then\n  begin\n    if ModRm in [$D0 .. $DF] then\n    begin\n      Decode_Invalid_FPU(PInst);\n      Exit;\n    end;\n  end;\n  Decode_NA_ModRm(PInst);\nend;\n\nprocedure Decode_Escape_FPU_DD(PInst: PInstruction);\nvar\n  P: PByte;\n  ModRm: Byte;\n  Reg: Byte;\nbegin\n  PInst^.OpTable := tbFPU;\n  P := PInst^.NextInst;\n  Inc(P);\n  ModRm := P^;\n  Reg := GetModRm_Reg(ModRm);\n  if ModRm < $C0 then\n  begin\n    if (Reg = $05) then\n    begin\n      Decode_Invalid_FPU(PInst);\n      Exit;\n    end;\n  end\n  else\n  begin\n    if ModRm in [$C8 .. $CF, $F0 .. $FF] then\n    begin\n      Decode_Invalid_FPU(PInst);\n      Exit;\n    end;\n  end;\n  Decode_NA_ModRm(PInst);\nend;\n\nprocedure Decode_Escape_FPU_DE(PInst: PInstruction);\nvar\n  P: PByte;\n  ModRm: Byte;\nbegin\n  PInst^.OpTable := tbFPU;\n  P := PInst^.NextInst;\n  Inc(P);\n  ModRm := P^;\n  if ModRm > $C0 then\n  begin\n    if ModRm in [$D0 .. $D8, $DA .. $DF] then\n    begin\n      Decode_Invalid_FPU(PInst);\n      Exit;\n    end;\n  end;\n  Decode_NA_ModRm(PInst);\nend;\n\nprocedure Decode_Escape_FPU_DF(PInst: PInstruction);\nvar\n  P: PByte;\n  ModRm: Byte;\nbegin\n  PInst^.OpTable := tbFPU;\n  P := PInst^.NextInst;\n  Inc(P);\n  ModRm := P^;\n  if ModRm > $C0 then\n  begin\n    if ModRm in [$C0 .. $CF, $D0 .. $DF, $E1 .. $E7, $F8 .. $FF] then\n    begin\n      Decode_Invalid_FPU(PInst);\n      Exit;\n    end;\n  end;\n  Decode_NA_ModRm(PInst);\nend;\n\n{ .$ENDREGION }\n{ .$REGION 'GROUPS' }\n{ ========================== GROUPS =============================== }\n\nprocedure Decode_Group_1(PInst: PInstruction);\nbegin\n  SetGroup(PInst);\n  if not(PInst^.NextInst^ in [$80 .. $83]) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  if PInst^.NextInst^ = $81 then\n    Decode_NA_ModRm_Iz(PInst)\n  else\n    Decode_NA_ModRm_Ib(PInst);\nend;\n\nprocedure Decode_Group_1A(PInst: PInstruction);\nvar\n  P: PByte;\n  Reg: Byte;\nbegin\n  SetGroup(PInst);\n  if (PInst^.NextInst^ <> $8F) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  P := PInst^.NextInst;\n  Inc(P); // ModRm !\n  Reg := GetModRm_Reg(P^);\n  if (Reg = $00) then\n  begin\n    Decode_NA_ModRm(PInst);\n    Exit;\n  end;\n  Decode_Invalid_Group(PInst);\nend;\n\nprocedure Decode_Group_2(PInst: PInstruction);\nbegin\n  SetGroup(PInst);\n  if not(PInst^.NextInst^ in [$C0 .. $C1, $D0 .. $D3]) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  if (PInst^.NextInst^ in [$C0, $C1]) then\n    Decode_NA_ModRm_Ib(PInst)\n  else\n    Decode_NA_ModRm(PInst);\nend;\n\nprocedure Decode_Group_3(PInst: PInstruction);\nvar\n  P: PByte;\n  Reg: Byte;\nbegin\n  SetGroup(PInst);\n  if not(PInst^.NextInst^ in [$F6, $F7]) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  P := PInst^.NextInst;\n  Inc(P);\n  Reg := GetModRm_Reg(P^);\n  if (Reg < $02) then\n  begin\n    { [TEST Reg,Immb] & [TEST Reg,Immz] }\n    if PInst^.NextInst^ = $F6 then\n      Decode_NA_ModRm_Ib(PInst)\n    else\n      Decode_NA_ModRm_Iz(PInst);\n    Exit;\n  end;\n  Decode_NA_ModRm(PInst);\nend;\n\nprocedure Decode_Group_4_INC_DEC(PInst: PInstruction);\nvar\n  P: PByte;\n  Reg: Byte;\nbegin\n  SetGroup(PInst);\n  Assert(PInst^.NextInst^ = $FE);\n  P := PInst^.NextInst;\n  Inc(P); // ModRm\n  Reg := GetModRm_Reg(P^);\n  if (Reg < $02) then\n  begin\n    { INC/DEC REG }\n    Decode_NA_ModRm(PInst);\n    Exit;\n  end;\n  Decode_Invalid_Group(PInst);\nend;\n\nprocedure Decode_Group_5_INC_DEC(PInst: PInstruction);\nvar\n  Reg: Byte;\n  P: PByte;\nconst\n  GroupProc: array [0 .. 7] of TDecoderProc = ( //\n    { 00 } Decode_NA_ModRm, { INC Ev }\n    { 01 } Decode_NA_ModRm, { DEC Ev }\n    { 02 } Decode_CALL_ModRm, { CALL Ev }\n    { 03 } Decode_CALL_Mp, { CALL Mp }\n    { 04 } Decode_JMP_ModRm, { JMP Ev }\n    { 05 } Decode_JMP_Mp, { JMP Mp }\n    { 06 } Decode_NA_ModRm, { PUSH Ev }\n    { 07 } Decode_Invalid_Group { InvalidOpCode }\n    );\nbegin\n  SetGroup(PInst);\n  if (PInst^.NextInst^ <> $FF) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  P := PInst^.NextInst;\n  Inc(P); // ModRm\n  Reg := GetModRm_Reg(P^);\n  GroupProc[Reg](PInst);\nend;\n\nprocedure Decode_Group_6(PInst: PInstruction);\nvar\n  P: PByte;\n  Reg: Byte;\nbegin\n  SetGroup(PInst);\n  if (PInst^.OpTable <> tbTwoByte) and (PInst^.NextInst^ <> $00) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  P := PInst^.NextInst;\n  Inc(P);\n  Reg := GetModRm_Reg(P^);\n  if Reg = $07 then\n  begin\n    Decode_Invalid_Group(PInst);\n    Exit;\n  end;\n  Decode_NA_ModRm(PInst);\nend;\n\nprocedure Decode_Group_7(PInst: PInstruction);\nvar\n  P: PByte;\n  iMod, Reg: Byte;\nbegin\n  SetGroup(PInst);\n  if (PInst^.OpTable <> tbTwoByte) and (PInst^.NextInst^ <> $01) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  P := PInst^.NextInst;\n  Inc(P);\n  iMod := GetModRm_Mod(P^);\n  Reg := GetModRm_Reg(P^);\n  if (Reg = $04) or (Reg = $06) then\n  begin\n    Decode_NA_ModRm(PInst);\n    Exit;\n  end\n  else if Reg = $05 then\n  begin\n    Decode_Invalid_Group(PInst);\n    Exit;\n  end;\n  if iMod <> $03 then\n  begin\n    Decode_NA_ModRm(PInst);\n    Exit;\n  end;\n  Decode_Invalid_Group(PInst);\nend;\n\nprocedure Decode_Group_8(PInst: PInstruction);\nvar\n  P: PByte;\n  Reg: Byte;\nbegin\n  SetGroup(PInst);\n  if (PInst^.OpTable <> tbTwoByte) and (PInst^.NextInst^ <> $BA) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  P := PInst^.NextInst;\n  Inc(P);\n  Reg := GetModRm_Reg(P^);\n  if Reg > $03 then\n  begin\n    Decode_NA_ModRm_Ib(PInst);\n    Exit;\n  end;\n  Decode_Invalid_Group(PInst);\nend;\n\nprocedure Decode_Group_9(PInst: PInstruction);\nvar\n  P: PByte;\n  iMod, Reg: Byte;\nbegin\n  SetGroup(PInst);\n  if (PInst^.OpTable <> tbTwoByte) and (PInst^.NextInst^ <> $C7) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  P := PInst^.NextInst;\n  Inc(P);\n  iMod := GetModRm_Mod(P^);\n  Reg := GetModRm_Reg(P^);\n  if (iMod = $03) and (Reg > $05) then\n  begin\n    Decode_NA_ModRm(PInst);\n    Exit;\n  end;\n\n  if (iMod <> $03) then\n  begin\n    { Mod = Mem }\n    if (((PInst^.LID.MndPrf = $00) and (Reg = $01)) or //\n      ((PInst^.LID.MndPrf = $66) and (Reg = $06)) or //\n      ((PInst^.LID.MndPrf = $F3) and (Reg > $05))) then\n    begin\n      Decode_NA_ModRm(PInst);\n      Exit;\n    end;\n  end;\n  Decode_Invalid_Group(PInst);\nend;\n\nprocedure Decode_Group_10_UD2(PInst: PInstruction);\nbegin\n  SetGroup(PInst);\n  Decode_InvalidOpCode(PInst);\nend;\n\nprocedure Decode_Group_11(PInst: PInstruction);\nvar\n  P: PByte;\n  Reg: Byte;\nbegin\n  SetGroup(PInst);\n  if not(PInst^.NextInst^ in [$C6, $C7]) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  P := PInst^.NextInst;\n  Inc(P);\n  Reg := GetModRm_Reg(P^);\n  if PInst^.NextInst^ = $C6 then\n  begin\n    if (Reg = $00) then\n    begin\n      { XABORT Instruction }\n      Decode_NA_ModRm_Ib(PInst);\n      Exit;\n    end\n    else if (Reg = $07) then\n    begin\n      Decode_NA_Ib(PInst);\n      Exit;\n    end\n  end\n  else if PInst^.NextInst^ = $C7 then\n  begin\n    if Reg = $00 then\n    begin\n      Decode_NA_ModRm_Iz(PInst);\n      Exit;\n    end\n    else if Reg = $07 then\n    begin\n      { XBEGIN Instruction }\n      SetOpCode(PInst);\n      Inc(PInst^.NextInst);\n      Decode_J(PInst, PInst^.LID.zOpSize);\n      PInst^.OpType := $00;\n      Exit;\n    end;\n  end;\n  Decode_Invalid_Group(PInst);\nend;\n\nprocedure Decode_Group_12(PInst: PInstruction);\nvar\n  P: PByte;\n  iMod, Reg: Byte;\nbegin\n  SetGroup(PInst);\n  { Group 12 & 13 }\n  if (PInst^.OpTable <> tbTwoByte) and not(PInst^.NextInst^ in [$71, $72]) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  P := PInst^.NextInst;\n  Inc(P);\n  iMod := GetModRm_Mod(P^);\n  Reg := GetModRm_Reg(P^);\n  if (iMod = $03) and (Reg in [$02, $04, $06]) then\n  begin\n    Decode_NA_ModRm_Ib(PInst);\n    Exit;\n  end;\n  Decode_Invalid_Group(PInst);\nend;\n\nprocedure Decode_Group_13(PInst: PInstruction);\nbegin\n  SetGroup(PInst);\n  { Group 13 has the same instructions signature as Group 12 ! }\n  Decode_Group_12(PInst);\nend;\n\nprocedure Decode_Group_14(PInst: PInstruction);\nvar\n  P: PByte;\n  iMod, Reg: Byte;\nbegin\n  SetGroup(PInst);\n  if (PInst^.OpTable <> tbTwoByte) and (PInst^.NextInst^ <> $73) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  P := PInst^.NextInst;\n  Inc(P);\n  iMod := GetModRm_Mod(P^);\n  Reg := GetModRm_Reg(P^);\n  if iMod = $03 then\n  begin\n    if (Reg = $02) or (Reg = $06) then\n    begin\n      Decode_NA_ModRm_Ib(PInst);\n      Exit;\n    end;\n    if (PInst^.LID.MndPrf = $66) and ((Reg = $03) or (Reg = $07)) then\n    begin\n      Decode_NA_ModRm_Ib(PInst);\n      Exit;\n    end;\n  end;\n  Decode_Invalid_Group(PInst);\nend;\n\nprocedure Decode_Group_15(PInst: PInstruction);\nvar\n  P: PByte;\n  iMod, Reg: Byte;\nbegin\n  SetGroup(PInst);\n  if (PInst^.OpTable <> tbTwoByte) and (PInst^.NextInst^ <> $AE) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  P := PInst^.NextInst;\n  Inc(P);\n  iMod := GetModRm_Mod(P^);\n  Reg := GetModRm_Reg(P^);\n  if (iMod = $03) and (PInst^.LID.MndPrf = $F3) and (Reg < $04) then\n  begin\n    Decode_NA_ModRm(PInst);\n    Exit;\n  end;\n  Decode_Invalid_Group(PInst);\nend;\n\nprocedure Decode_Group_16(PInst: PInstruction);\nvar\n  P: PByte;\n  iMod, Reg: Byte;\nbegin\n  SetGroup(PInst);\n  if (PInst^.OpTable <> tbTwoByte) and (PInst^.NextInst^ <> $18) then\n    SetInstError(PInst, INVALID_GROUP_OPCODE);\n  P := PInst^.NextInst;\n  Inc(P);\n  iMod := GetModRm_Mod(P^);\n  Reg := GetModRm_Reg(P^);\n  if (iMod <> $03) and (Reg < $04) then\n  begin\n    { Prefetch group instructions. }\n    Decode_NA_ModRm(PInst);\n    Exit;\n  end;\n  Decode_Invalid_Group(PInst);\nend;\n\nprocedure Decode_Group_17(PInst: PInstruction);\nvar\n  P: PByte;\n  Reg: Byte;\nbegin\n  SetGroup(PInst);\n  P := PInst^.NextInst;\n  Inc(P);\n  Reg := GetModRm_Reg(P^);\n  if (Reg > $00) and (Reg < $04) then\n  begin\n    Decode_NA_ModRm(PInst);\n    Exit;\n  end;\n  Decode_Invalid_Group(PInst);\nend;\n\n{ .$ENDREGION }\n{ .$REGION 'DECODERS' }\n{ ========================== DECODERS PROC =============================== }\n\nprocedure Decode_NA_CALL_Ap_I64(PInst: PInstruction);\nbegin\n  { Instruction is only valid for x32 ! }\n  if PInst^.Archi = CPUX64 then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  PInst^.OpType := otCALL;\n  Decode_Ap(PInst);\nend;\n\nprocedure Decode_NA_ModRm(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\nend;\n\nprocedure Decode_NA_Ib(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_Imm(PInst, ops8bits);\nend;\n\nprocedure Decode_NA_Iz(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_Imm(PInst, PInst^.LID.zOpSize);\nend;\n\nprocedure Decode_NA_I64(PInst: PInstruction);\nbegin\n  { Instruction is invalid on PM64 }\n  { Only valid when mandatory prefix is : $00 }\n  if (PInst^.Archi = CPUX64) or ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\nend;\n\nprocedure Decode_NA(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\nend;\n\nprocedure Decode_NA_ModRm_I64(PInst: PInstruction);\nbegin\n  { Instruction is invalid on PM64 }\n  { Only valid when mandatory prefix is : $00 }\n  if (PInst^.Archi = CPUX64) or ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\nend;\n\nprocedure Decode_NA_ModRm_Iz(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\n  Decode_Imm(PInst, PInst^.LID.zOpSize);\nend;\n\nprocedure Decode_NA_ModRm_Ib(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\n  Decode_Imm(PInst, ops8bits);\nend;\n\nprocedure Decode_NA_Jb_Df64(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf <> $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  PInst^.OperandFlags := opdDf64;\n  Decode_J(PInst, ops8bits);\nend;\n\nprocedure Decode_NA_RET(PInst: PInstruction);\nbegin\n  SetOpCode(PInst);\n  PInst^.OpType := otRET;\n  if PInst^.OpCode in [$C2, $CA] then\n    Decode_Imm(PInst, ops16bits);\nend;\n\nprocedure Decode_NA_Ib_I64(PInst: PInstruction);\nbegin\n  { Instruction is invalid on PM64 }\n  { Only valid when mandatory prefix is : $00 }\n  if (PInst^.Archi = CPUX64) or ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_Imm(PInst, ops8bits);\nend;\n\nprocedure Decode_NA_CALL_Jz_Df64(PInst: PInstruction);\nbegin\n  SetOpCode(PInst);\n  PInst^.OpType := otCALL;\n  PInst^.OperandFlags := opdDf64;\n  Decode_J(PInst, PInst^.LID.zOpSize);\nend;\n\nprocedure Decode_NA_JMP_Jz_Df64(PInst: PInstruction);\nbegin\n  SetOpCode(PInst);\n  PInst^.OpType := otJMP;\n  PInst^.OperandFlags := opdDf64;\n  Decode_J(PInst, PInst^.LID.zOpSize);\nend;\n\nprocedure Decode_NA_JMP_Ap_I64(PInst: PInstruction);\nbegin\n  if PInst^.Archi = CPUX64 then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  PInst^.OpType := otJMP;\n  Decode_Ap(PInst);\nend;\n\nprocedure Decode_NA_JMP_Jb_Df64(PInst: PInstruction);\nbegin\n  SetOpCode(PInst);\n  PInst^.OpType := otJMP;\n  PInst^.OperandFlags := opdDf64;\n  Decode_J(PInst, ops8bits);\nend;\n\nprocedure Decode_CALL_ModRm(PInst: PInstruction);\nbegin\n  PInst^.OpType := otCALL;\n  Decode_Branch_ModRm(PInst);\nend;\n\nprocedure Decode_CALL_Mp(PInst: PInstruction);\nbegin\n  PInst^.OpType := otCALL;\n  Decode_Mp(PInst);\nend;\n\nprocedure Decode_JMP_ModRm(PInst: PInstruction);\nbegin\n  PInst^.OpType := otJMP;\n  Decode_Branch_ModRm(PInst);\nend;\n\nprocedure Decode_JMP_Mp(PInst: PInstruction);\nbegin\n  PInst^.OpType := otJMP;\n  Decode_Mp(PInst);\nend;\n\nprocedure Decode_NA_CALL(PInst: PInstruction);\nbegin\n  { SYSCALL! }\n  SetOpCode(PInst);\nend;\n\nprocedure Decode_NA_66_F2_F3_ModRm(PInst: PInstruction);\nbegin\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\nend;\n\nprocedure Decode_NA_66_ModRm(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 or $66 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf in [$00, $66])) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\nend;\n\nprocedure Decode_NA_66_F3_ModRm(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 or $66 or $F3 }\n  if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf = $F2)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\nend;\n\nprocedure Decode_NA_F3_ModRm(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 or $F3 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf in [$00, $F3])) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\nend;\n\nprocedure Decode_66_ModRm(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $66 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $66)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\nend;\n\nprocedure Decode_NA_66_F2_F3_ModRm_Ib(PInst: PInstruction);\nbegin\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\n  Decode_Imm(PInst, ops8bits);\nend;\n\nprocedure Decode_66_F2_ModRm(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $66 or $F2 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf in [$66, $F2])) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\nend;\n\nprocedure Decode_F3_ModRm(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $F3 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $F3)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\nend;\n\nprocedure Decode_NA_66_ModRm_Ib(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 or $66 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf in [$00, $66])) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\n  Decode_Imm(PInst, ops8bits);\nend;\n\nprocedure Decode_66_F2_F3_ModRm(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $66 or $F2 or $F3 }\n  if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf = $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\nend;\n\nprocedure Decode_F2_ModRm(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $F2 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $F2)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\nend;\n\nprocedure Decode_SP_T38_F0_F7(PInst: PInstruction);\nvar\n  Prf66F2: Boolean;\nbegin\n  if PInst^.NextInst^ = $F3 then\n  begin\n    Decode_Group_17(PInst);\n    Exit;\n  end;\n\n  { 66 & F2 }\n  Prf66F2 := PInst^.Prefixes and (Prf_OpSize or Prf_Repne) = (Prf_OpSize or Prf_Repne);\n\n  if Prf66F2 then\n  begin\n    { Valid only for CRC32 instruction ! }\n    if (PInst^.NextInst^ = $F0) or (PInst^.NextInst^ = $F1) then\n    begin\n      Decode_NA_ModRm(PInst);\n      Exit;\n    end\n    else\n    begin\n      Decode_InvalidOpCode(PInst);\n      Exit;\n    end;\n  end\n  else if PInst^.LID.MndPrf = $00 then\n  begin\n    if (PInst^.NextInst^ = $F4) or (PInst^.NextInst^ = $F6) then\n    begin\n      Decode_InvalidOpCode(PInst);\n      Exit;\n    end;\n  end\n  else if PInst^.LID.MndPrf = $66 then\n  begin\n    if (PInst^.NextInst^ in [$F2 .. $F5]) then\n    begin\n      Decode_InvalidOpCode(PInst);\n      Exit;\n    end;\n  end\n  else if PInst^.LID.MndPrf = $F3 then\n  begin\n    if (PInst^.NextInst^ < $F5) then\n    begin\n      Decode_InvalidOpCode(PInst);\n      Exit;\n    end;\n  end\n  else if PInst^.LID.MndPrf = $F2 then\n  begin\n    if (PInst^.NextInst^ in [$F2 .. $F4]) then\n    begin\n      Decode_InvalidOpCode(PInst);\n      Exit;\n    end;\n  end;\n  Decode_NA_ModRm(PInst);\nend;\n\nprocedure Decode_66_ModRm_Ib(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $66 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $66)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\n  Decode_Imm(PInst, ops8bits);\nend;\n\nprocedure Decode_F2_ModRm_Ib(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $F2 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $F2)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_ModRm(PInst);\n  Decode_Imm(PInst, ops8bits);\nend;\n\nprocedure Decode_NA_RET_Iw_Df64(PInst: PInstruction);\nbegin\n  PInst^.OpType := otRET;\n  SetOpCode(PInst);\n  PInst^.OperandFlags := opdDf64;\n  Decode_Imm(PInst, ops16bits);\nend;\n\nprocedure Decode_NA_D64(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf <> $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  PInst^.OperandFlags := opdD64;\nend;\n\nprocedure Decode_NA_Iz_D64(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf <> $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  PInst^.OperandFlags := opdD64;\n  Decode_Imm(PInst, PInst^.LID.zOpSize);\nend;\n\nprocedure Decode_NA_Ib_D64(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf <> $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  PInst^.OperandFlags := opdD64;\n  Decode_Imm(PInst, ops8bits);\nend;\n\nprocedure Decode_NA_RET_Df64(PInst: PInstruction);\nbegin\n  PInst^.OpType := otRET;\n  PInst^.OperandFlags := opdDf64;\n  SetOpCode(PInst);\nend;\n\nprocedure Decode_NA_RET_Iw(PInst: PInstruction);\nbegin\n  PInst^.OpType := otRET;\n  SetOpCode(PInst);\n  Decode_Imm(PInst, ops16bits);\nend;\n\nprocedure Decode_NA_Iw_Ib_D64(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf <> $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  PInst^.OperandFlags := opdD64;\n  Decode_Imm(PInst, ops16bits);\n  Decode_Imm(PInst, ops8bits);\nend;\n\nprocedure Decode_NA_ModRm_F64(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf <> $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  PInst^.OperandFlags := opdF64;\n  Decode_ModRm(PInst);\nend;\n\nprocedure Decode_NA_Jz_Df64(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and (PInst^.LID.MndPrf <> $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  PInst^.OperandFlags := opdDf64;\n  Decode_J(PInst, PInst^.LID.zOpSize);\nend;\n\nprocedure Decode_NA_OfstV(PInst: PInstruction);\nbegin\n  SetOpCode(PInst);\n  Decode_Imm(PInst, PInst.LID.vOpSize);\n  PInst.Disp.Value := PInst.Imm.Value;\n  PInst.Disp.Size := PInst.Imm.Size;\n  PInst.Disp.Flags := dfUsed or dfOffset;\n  PInst.Imm.Size := $00;\n  PInst.Imm.Value := $00;\n  PInst.Imm.Flags := $00;\nend;\n\nprocedure Decode_NA_Iv(PInst: PInstruction);\nbegin\n  { Only valid when mandatory prefix is : $00 }\n  if ((PInst^.OpTable <> tbOneByte) and not(PInst^.LID.MndPrf = $00)) then\n  begin\n    Decode_InvalidOpCode(PInst);\n    Exit;\n  end;\n  SetOpCode(PInst);\n  Decode_Imm(PInst, PInst^.LID.vOpSize);\nend;\n{ .$ENDREGION }\n\nfunction DecodeInst(PInst: PInstruction): Integer;\nvar\n  P: PByte;\n  LArchi: Byte;\n  LAddr: PByte;\n  LErrors: Byte;\n  LVA: PByte;\n  LOptions: Byte;\nbegin\n  { No Errors }\n  SetInstError(PInst, NO_ERROR);\n\n  if not(PInst^.Archi in [CPUX32, CPUX64]) then\n    SetInstError(PInst, INVALID_CPUX);\n\n  if not Assigned(PInst^.Addr) then\n    SetInstError(PInst, INVALID_ADDRESS);\n\n  { Init Instruction Structure }\n  LArchi := PInst^.Archi;\n  LAddr := PInst^.Addr;\n  LVA := PInst^.VirtualAddr;\n  LErrors := PInst^.Errors;\n  LOptions := PInst^.Options;\n\n  FillChar(PInst^, SizeOf(TInstruction), #0);\n\n  PInst^.Archi := LArchi;\n  PInst^.Addr := LAddr;\n  PInst^.Errors := LErrors;\n  PInst^.VirtualAddr := LVA;\n  PInst.Options := LOptions;\n\n  P := PInst^.Addr;\n  PInst^.NextInst := P;\n\n  PInst^.LID.zOpSize := ops32bits;\n  PInst^.LID.vOpSize := ops32bits;\n  PInst^.AddrMode := DefAddressMode[PInst^.Archi];\n\n  { Default Op Table is One Byte ! }\n  PInst^.OpTable := tbOneByte;\n\n  DecoderProcTable[OneByteTable[P^]](PInst);\n  Result := Integer(NativeInt(PInst^.NextInst) - NativeInt(P));\n  PInst^.InstSize := Result;\n\n  if Result > CPUX_TO_INST_LENGTH[PInst^.Archi] then\n    SetInstError(PInst, INVALID_INSTRUCTION_LENGTH);\nend;\n\nend.\n"
  },
  {
    "path": "Source/LegacyTypes.pas",
    "content": "// **************************************************************************************************\n//\n// https://github.com/MahdiSafsafi/DDetours\n//\n// **************************************************************************************************\n\nunit LegacyTypes;\n\ninterface\n\n{$I DDetoursDefs.inc}\n\ntype\n\n{$IFNDEF FPC}\n{$IFNDEF DELPHI_XE_UP}\n  NativeInt   = Integer;\n  NativeUInt  = Cardinal;\n  PNativeInt  = ^NativeInt;\n  PNativeUInt = ^NativeUInt;\n{$IFDEF MSWINDOWS}\n  TThreadID = LongWord;\n{$ENDIF MSWINDOWS}\n{$ENDIF DELPHI_XE_UP}\n{$ENDIF FPC}\n  Int8 = Shortint;\n  Int16 = Smallint;\n  Int32 = Integer;\n\n  UInt8 = Byte;\n  UInt16 = Word;\n  UInt32 = Cardinal;\n\n  PInt8 = ^Int8;\n  PInt16 = ^Int16;\n  PInt32 = ^Int32;\n  PInt64 = ^Int64;\n\n  PUInt8 = ^UInt8;\n  PUInt16 = ^UInt16;\n  PUInt32 = ^UInt32;\n  PUInt64 = ^UInt64;\n\n  SIZE_T = NativeUInt;\n\nimplementation\n\nend.\n"
  },
  {
    "path": "Source/ModRmFlagsTables.inc",
    "content": "// **************************************************************************************************\n// Part of x86 Instruction Decode Library [InstDecode]\n// \n// https://github.com/MahdiSafsafi/DDetours\n//\n// This Source Code Form is subject to the terms of the Mozilla \n// Public License, v. 2.0. If a copy of the MPL was not distributed \n// with this file, You can obtain one at\n// https://mozilla.org/MPL/2.0/.\n// **************************************************************************************************\n\n\n{ Reference : Intel® 64 and IA-32 Architectures Software Developer’s Manual Vol 2 }\n\ntype\n  TModRmFlagsArray = array [Byte] of Byte;\n  PModRmFlagsArray = ^TModRmFlagsArray;\n  {\n    ModRMFlags :\n    Bits:4 3 2 1 0 .\n\n    Bit 0 : Set ==> Register Indirect Addressing Mode  .\n    Bit 1 : Set ==> Displacement 8 bit .\n    Bit 2 : Set ==> Displacement 16 bit .\n    Bit 3 : Set ==> Displacement 32 bit.\n    Bit 4 : Set ==> SIB Used  .\n\n\n    Values:\n\n    $00 ==> Register .\n    $01 ==> Register Indirect Addressing Mode with No Displacement .\n    $03 ==> Register Indirect Addressing Mode + 8 bit Displacement .\n    $04 ==> 16 bit Displacement only without register .\n    $05 ==> Register Indirect Addressing Mode + 16 bit Displacement .\n    $08 ==> 32 bit Displacement only without register .\n    $09 ==> Register Indirect Addressing Mode + 32 bit Displacement .\n    $11 ==>  Register Indirect Addressing Mode + SIB .\n    $13 ==> Register Indirect Addressing Mode + SIB + 8 bit Displacement .\n    $19 ==> Register Indirect Addressing Mode + SIB + 32 bit Displacement .\n\n  }\n\nconst\n\n  ModRM16Flags: TModRmFlagsArray = (\n    { =>        Mod=00b       <= }\n    $01, $01, $01, $01, $01, $01, $04, $01, { 00 }\n    $01, $01, $01, $01, $01, $01, $04, $01, { 00 }\n    $01, $01, $01, $01, $01, $01, $04, $01, { 00 }\n    $01, $01, $01, $01, $01, $01, $04, $01, { 00 }\n    $01, $01, $01, $01, $01, $01, $04, $01, { 00 }\n    $01, $01, $01, $01, $01, $01, $04, $01, { 00 }\n    $01, $01, $01, $01, $01, $01, $04, $01, { 00 }\n    $01, $01, $01, $01, $01, $01, $04, $01, { 00 }\n    { =>        Mod=01b       <= }\n    $03, $03, $03, $03, $03, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $03, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $03, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $03, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $03, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $03, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $03, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $03, $03, $03, $03, { 01 }\n    { =>        Mod=10b       <= }\n    $05, $05, $05, $05, $05, $05, $05, $05, { 10 }\n    $05, $05, $05, $05, $05, $05, $05, $05, { 10 }\n    $05, $05, $05, $05, $05, $05, $05, $05, { 10 }\n    $05, $05, $05, $05, $05, $05, $05, $05, { 10 }\n    $05, $05, $05, $05, $05, $05, $05, $05, { 10 }\n    $05, $05, $05, $05, $05, $05, $05, $05, { 10 }\n    $05, $05, $05, $05, $05, $05, $05, $05, { 10 }\n    $05, $05, $05, $05, $05, $05, $05, $05, { 10 }\n    { =>        Mod=11b       <= }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00 { 11 }\n\n    );\n  ModRM32Flags: TModRmFlagsArray = (\n    { =>        Mod=00b       <= }\n    $01, $01, $01, $01, $11, $08, $01, $01, { 00 }\n    $01, $01, $01, $01, $11, $08, $01, $01, { 00 }\n    $01, $01, $01, $01, $11, $08, $01, $01, { 00 }\n    $01, $01, $01, $01, $11, $08, $01, $01, { 00 }\n    $01, $01, $01, $01, $11, $08, $01, $01, { 00 }\n    $01, $01, $01, $01, $11, $08, $01, $01, { 00 }\n    $01, $01, $01, $01, $11, $08, $01, $01, { 00 }\n    $01, $01, $01, $01, $11, $08, $01, $01, { 00 }\n    { =>        Mod=01b       <= }\n    $03, $03, $03, $03, $13, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $13, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $13, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $13, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $13, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $13, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $13, $03, $03, $03, { 01 }\n    $03, $03, $03, $03, $13, $03, $03, $03, { 01 }\n    { =>        Mod=10b       <= }\n    $09, $09, $09, $09, $19, $09, $09, $09, { 10 }\n    $09, $09, $09, $09, $19, $09, $09, $09, { 10 }\n    $09, $09, $09, $09, $19, $09, $09, $09, { 10 }\n    $09, $09, $09, $09, $19, $09, $09, $09, { 10 }\n    $09, $09, $09, $09, $19, $09, $09, $09, { 10 }\n    $09, $09, $09, $09, $19, $09, $09, $09, { 10 }\n    $09, $09, $09, $09, $19, $09, $09, $09, { 10 }\n    $09, $09, $09, $09, $19, $09, $09, $09, { 10 }\n    { =>        Mod=11b       <= }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00, { 11 }\n    $00, $00, $00, $00, $00, $00, $00, $00 { 11 }\n\n    );\n\n  ModRmFlags: array [0 .. 3] of PModRmFlagsArray = ( //\n    nil,\n    @ModRM16Flags, { AddrMode 16-bits }\n    @ModRM32Flags, { AddrMode 32-bits }\n    @ModRM32Flags { AddrMode 64-bits }\n    );"
  },
  {
    "path": "Source/OpCodesTables.inc",
    "content": "// **************************************************************************************************\n// Part of x86 Instruction Decode Library [InstDecode]\n// \n// https://github.com/MahdiSafsafi/DDetours\n//\n// This Source Code Form is subject to the terms of the Mozilla \n// Public License, v. 2.0. If a copy of the MPL was not distributed \n// with this file, You can obtain one at\n// https://mozilla.org/MPL/2.0/.\n// **************************************************************************************************\n\n{ Reference :\n\t-sandpile.org\n\t-Intel® 64 and IA-32 Architectures Software Developer’s Manual Vol 2\n}\n\n{ ============================================\n\t\t\tIndex -> DecoderProc\n  ============================================ }\n{ 00 = Decode_InvalidOpCode}\n{ 01 = Decode_NA_ModRm}\n{ 02 = Decode_NA_Ib}\n{ 03 = Decode_NA_Iz}\n{ 04 = Decode_NA_I64}\n{ 05 = Decode_Escape_2_Byte}\n{ 06 = Decode_ES_Prefix}\n{ 07 = Decode_CS_Prefix}\n{ 08 = Decode_SS_Prefix}\n{ 09 = Decode_DS_Prefix}\n{ 10 = Decode_REX_Prefix}\n{ 11 = Decode_NA_D64}\n{ 12 = Decode_NA_ModRm_I64}\n{ 13 = Decode_FS_Prefix}\n{ 14 = Decode_GS_Prefix}\n{ 15 = Decode_OPSIZE_Prefix}\n{ 16 = Decode_ADSIZE_Prefix}\n{ 17 = Decode_NA_Iz_D64}\n{ 18 = Decode_NA_ModRm_Iz}\n{ 19 = Decode_NA_Ib_D64}\n{ 20 = Decode_NA_ModRm_Ib}\n{ 21 = Decode_NA}\n{ 22 = Decode_NA_Jb_Df64}\n{ 23 = Decode_Group_1}\n{ 24 = Decode_Group_1A}\n{ 25 = Decode_NA_CALL_Ap_I64}\n{ 26 = Decode_NA_OfstV}\n{ 27 = Decode_NA_Iv}\n{ 28 = Decode_Group_2}\n{ 29 = Decode_NA_RET_Iw_Df64}\n{ 30 = Decode_NA_RET_Df64}\n{ 31 = Decode_VEX3_Prefix}\n{ 32 = Decode_VEX2_Prefix}\n{ 33 = Decode_Group_11}\n{ 34 = Decode_NA_Iw_Ib_D64}\n{ 35 = Decode_NA_RET_Iw}\n{ 36 = Decode_NA_RET}\n{ 37 = Decode_NA_Ib_I64}\n{ 38 = Decode_Escape_FPU_D8}\n{ 39 = Decode_Escape_FPU_D9}\n{ 40 = Decode_Escape_FPU_DA}\n{ 41 = Decode_Escape_FPU_DB}\n{ 42 = Decode_Escape_FPU_DC}\n{ 43 = Decode_Escape_FPU_DD}\n{ 44 = Decode_Escape_FPU_DE}\n{ 45 = Decode_Escape_FPU_DF}\n{ 46 = Decode_NA_CALL_Jz_Df64}\n{ 47 = Decode_NA_JMP_Jz_Df64}\n{ 48 = Decode_NA_JMP_Ap_I64}\n{ 49 = Decode_NA_JMP_Jb_Df64}\n{ 50 = Decode_LOCK_Prefix}\n{ 51 = Decode_REPNE_Prefix}\n{ 52 = Decode_REPE_Prefix}\n{ 53 = Decode_Group_3}\n{ 54 = Decode_Group_4_INC_DEC}\n{ 55 = Decode_Group_5_INC_DEC}\n{ 56 = Decode_Group_6}\n{ 57 = Decode_Group_7}\n{ 58 = Decode_NA_CALL}\n{ 59 = Decode_NA_66_F2_F3_ModRm}\n{ 60 = Decode_NA_66_ModRm}\n{ 61 = Decode_NA_66_F3_ModRm}\n{ 62 = Decode_Group_16}\n{ 63 = Decode_NA_ModRm_F64}\n{ 64 = Decode_Escape_3_Byte}\n{ 65 = Decode_NA_F3_ModRm}\n{ 66 = Decode_66_ModRm}\n{ 67 = Decode_NA_66_F2_F3_ModRm_Ib}\n{ 68 = Decode_Group_12}\n{ 69 = Decode_Group_13}\n{ 70 = Decode_Group_14}\n{ 71 = Decode_66_F2_ModRm}\n{ 72 = Decode_NA_Jz_Df64}\n{ 73 = Decode_Group_15}\n{ 74 = Decode_F3_ModRm}\n{ 75 = Decode_Group_10_UD2}\n{ 76 = Decode_Group_8}\n{ 77 = Decode_NA_66_ModRm_Ib}\n{ 78 = Decode_Group_9}\n{ 79 = Decode_66_F2_F3_ModRm}\n{ 80 = Decode_F2_ModRm}\n{ 81 = Decode_SP_T38_F0_F7}\n{ 82 = Decode_66_ModRm_Ib}\n{ 83 = Decode_F2_ModRm_Ib}\n\n{============================================\n                  OneByteTable                    \n============================================}\nconst OneByteTable : array[Byte] of Byte =(//\n{0x00} 01, {ADD}\n{0x01} 01, {ADD}\n{0x02} 01, {ADD}\n{0x03} 01, {ADD}\n{0x04} 02, {ADD}\n{0x05} 03, {ADD}\n{0x06} 04, {PUSH}\n{0x07} 04, {POP}\n{0x08} 01, {OR}\n{0x09} 01, {OR}\n{0x0A} 01, {OR}\n{0x0B} 01, {OR}\n{0x0C} 02, {OR}\n{0x0D} 03, {OR}\n{0x0E} 04, {PUSH}\n{0x0F} 05, {Escape_2_Byte}\n{0x10} 01, {ADC}\n{0x11} 01, {ADC}\n{0x12} 01, {ADC}\n{0x13} 01, {ADC}\n{0x14} 02, {ADC}\n{0x15} 03, {ADC}\n{0x16} 04, {PUSH}\n{0x17} 04, {POP}\n{0x18} 01, {SBB}\n{0x19} 01, {SBB}\n{0x1A} 01, {SBB}\n{0x1B} 01, {SBB}\n{0x1C} 02, {SBB}\n{0x1D} 03, {SBB}\n{0x1E} 04, {PUSH}\n{0x1F} 04, {POP}\n{0x20} 01, {AND}\n{0x21} 01, {AND}\n{0x22} 01, {AND}\n{0x23} 01, {AND}\n{0x24} 02, {AND}\n{0x25} 03, {AND}\n{0x26} 06, {ES_Prefix}\n{0x27} 04, {DAA}\n{0x28} 01, {SUB}\n{0x29} 01, {SUB}\n{0x2A} 01, {SUB}\n{0x2B} 01, {SUB}\n{0x2C} 02, {SUB}\n{0x2D} 03, {SUB}\n{0x2E} 07, {CS_Prefix}\n{0x2F} 04, {DAS}\n{0x30} 01, {XOR}\n{0x31} 01, {XOR}\n{0x32} 01, {XOR}\n{0x33} 01, {XOR}\n{0x34} 02, {XOR}\n{0x35} 03, {XOR}\n{0x36} 08, {SS_Prefix}\n{0x37} 04, {AAA}\n{0x38} 01, {CMP}\n{0x39} 01, {CMP}\n{0x3A} 01, {CMP}\n{0x3B} 01, {CMP}\n{0x3C} 02, {CMP}\n{0x3D} 03, {CMP}\n{0x3E} 09, {DS_Prefix}\n{0x3F} 04, {AAS}\n{0x40} 10, {INC/REX_Prefix}\n{0x41} 10, {INC/REX_Prefix}\n{0x42} 10, {INC/REX_Prefix}\n{0x43} 10, {INC/REX_Prefix}\n{0x44} 10, {INC/REX_Prefix}\n{0x45} 10, {INC/REX_Prefix}\n{0x46} 10, {INC/REX_Prefix}\n{0x47} 10, {INC/REX_Prefix}\n{0x48} 10, {DEC/REX_Prefix}\n{0x49} 10, {DEC/REX_Prefix}\n{0x4A} 10, {DEC/REX_Prefix}\n{0x4B} 10, {DEC/REX_Prefix}\n{0x4C} 10, {DEC/REX_Prefix}\n{0x4D} 10, {DEC/REX_Prefix}\n{0x4E} 10, {DEC/REX_Prefix}\n{0x4F} 10, {DEC/REX_Prefix}\n{0x50} 11, {PUSH}\n{0x51} 11, {PUSH}\n{0x52} 11, {PUSH}\n{0x53} 11, {PUSH}\n{0x54} 11, {PUSH}\n{0x55} 11, {PUSH}\n{0x56} 11, {PUSH}\n{0x57} 11, {PUSH}\n{0x58} 11, {POP}\n{0x59} 11, {POP}\n{0x5A} 11, {POP}\n{0x5B} 11, {POP}\n{0x5C} 11, {POP}\n{0x5D} 11, {POP}\n{0x5E} 11, {POP}\n{0x5F} 11, {POP}\n{0x60} 04, {PUSHAD/PUSHA}\n{0x61} 04, {POPAD/POPA}\n{0x62} 12, {BOUND}\n{0x63} 01, {ARPL/MOVSXD}\n{0x64} 13, {FS_Prefix}\n{0x65} 14, {GS_Prefix}\n{0x66} 15, {OPSIZE_Prefix}\n{0x67} 16, {ADSIZE_Prefix}\n{0x68} 17, {PUSH}\n{0x69} 18, {IMUL}\n{0x6A} 19, {PUSH}\n{0x6B} 20, {IMUL}\n{0x6C} 21, {INS}\n{0x6D} 21, {INS}\n{0x6E} 21, {OUTS}\n{0x6F} 21, {OUTS}\n{0x70} 22, {JO}\n{0x71} 22, {JNO}\n{0x72} 22, {JB}\n{0x73} 22, {JNB}\n{0x74} 22, {JZ}\n{0x75} 22, {JNZ}\n{0x76} 22, {JBE}\n{0x77} 22, {JNBE}\n{0x78} 22, {JS}\n{0x79} 22, {JNS}\n{0x7A} 22, {JP}\n{0x7B} 22, {JNP}\n{0x7C} 22, {JL}\n{0x7D} 22, {JNL}\n{0x7E} 22, {JLE}\n{0x7F} 22, {JNLE}\n{0x80} 23, {group_1}\n{0x81} 23, {group_1}\n{0x82} 23, {group_1*}\n{0x83} 23, {group_1}\n{0x84} 01, {TEST}\n{0x85} 01, {TEST}\n{0x86} 01, {XCHG}\n{0x87} 01, {XCHG}\n{0x88} 01, {MOV}\n{0x89} 01, {MOV}\n{0x8A} 01, {MOV}\n{0x8B} 01, {MOV}\n{0x8C} 01, {MOV}\n{0x8D} 01, {LEA}\n{0x8E} 01, {MOV}\n{0x8F} 24, {group_1A}\n{0x90} 21, {PAUSE/NOP}\n{0x91} 21, {XCHG}\n{0x92} 21, {XCHG}\n{0x93} 21, {XCHG}\n{0x94} 21, {XCHG}\n{0x95} 21, {XCHG}\n{0x96} 21, {XCHG}\n{0x97} 21, {XCHG}\n{0x98} 21, {CWDE/CBW/CDQE}\n{0x99} 21, {CDQ/CWD/CQO}\n{0x9A} 25, {CALL}\n{0x9B} 21, {WAIT}\n{0x9C} 11, {PUSHF}\n{0x9D} 11, {POPF}\n{0x9E} 21, {SAHF}\n{0x9F} 21, {LAHF}\n{0xA0} 26, {MOV}\n{0xA1} 26, {MOV}\n{0xA2} 26, {MOV}\n{0xA3} 26, {MOV}\n{0xA4} 21, {MOVS}\n{0xA5} 21, {MOVS}\n{0xA6} 21, {CMPS}\n{0xA7} 21, {CMPS}\n{0xA8} 02, {TEST}\n{0xA9} 03, {TEST}\n{0xAA} 21, {STOS}\n{0xAB} 21, {STOS}\n{0xAC} 21, {LODS}\n{0xAD} 21, {LODS}\n{0xAE} 21, {SCAS}\n{0xAF} 21, {SCAS}\n{0xB0} 02, {MOV}\n{0xB1} 02, {MOV}\n{0xB2} 02, {MOV}\n{0xB3} 02, {MOV}\n{0xB4} 02, {MOV}\n{0xB5} 02, {MOV}\n{0xB6} 02, {MOV}\n{0xB7} 02, {MOV}\n{0xB8} 27, {MOV}\n{0xB9} 27, {MOV}\n{0xBA} 27, {MOV}\n{0xBB} 27, {MOV}\n{0xBC} 27, {MOV}\n{0xBD} 27, {MOV}\n{0xBE} 27, {MOV}\n{0xBF} 27, {MOV}\n{0xC0} 28, {group_2}\n{0xC1} 28, {group_2}\n{0xC2} 29, {RET}\n{0xC3} 30, {RET}\n{0xC4} 31, {LES/VEX3_Prefix}\n{0xC5} 32, {LDS/VEX2_Prefix}\n{0xC6} 33, {group_11}\n{0xC7} 33, {group_11}\n{0xC8} 34, {ENTER}\n{0xC9} 11, {LEAVE}\n{0xCA} 35, {RET}\n{0xCB} 36, {RET}\n{0xCC} 21, {INT3}\n{0xCD} 02, {INT}\n{0xCE} 04, {INTO}\n{0xCF} 36, {IRET}\n{0xD0} 28, {group_2}\n{0xD1} 28, {group_2}\n{0xD2} 28, {group_2}\n{0xD3} 28, {group_2}\n{0xD4} 37, {AAM}\n{0xD5} 37, {AAD}\n{0xD6} 04, {SETALC}\n{0xD7} 21, {XLAT}\n{0xD8} 38, {Escape_FPU_D8}\n{0xD9} 39, {Escape_FPU_D9}\n{0xDA} 40, {Escape_FPU_DA}\n{0xDB} 41, {Escape_FPU_DB}\n{0xDC} 42, {Escape_FPU_DC}\n{0xDD} 43, {Escape_FPU_DD}\n{0xDE} 44, {Escape_FPU_DE}\n{0xDF} 45, {Escape_FPU_DF}\n{0xE0} 22, {LOOPNZ/LOOPNE}\n{0xE1} 22, {LOOPZ/LOOPE}\n{0xE2} 22, {LOOP}\n{0xE3} 22, {JRCX/JECX/JCXZ}\n{0xE4} 02, {IN}\n{0xE5} 02, {IN}\n{0xE6} 02, {OUT}\n{0xE7} 02, {OUT}\n{0xE8} 46, {CALL}\n{0xE9} 47, {JMP}\n{0xEA} 48, {JMP}\n{0xEB} 49, {JMP}\n{0xEC} 21, {IN}\n{0xED} 21, {IN}\n{0xEE} 21, {OUT}\n{0xEF} 21, {OUT}\n{0xF0} 50, {LOCK_Prefix}\n{0xF1} 21, {INT1}\n{0xF2} 51, {REPNE_Prefix}\n{0xF3} 52, {REPE_Prefix}\n{0xF4} 21, {HLT}\n{0xF5} 21, {CMC}\n{0xF6} 53, {group_3}\n{0xF7} 53, {group_3}\n{0xF8} 21, {CLC}\n{0xF9} 21, {STC}\n{0xFA} 21, {CLI}\n{0xFB} 21, {STI}\n{0xFC} 21, {CLD}\n{0xFD} 21, {STD}\n{0xFE} 54, {group_4_INC_DEC}\n{0xFF} 55 {group_5_INC_DEC}\n);\n{============================================\n                  TwoByteTable                    \n============================================}\nconst TwoByteTable : array[Byte] of Byte =(//\n{0x00} 56, {group_6}\n{0x01} 57, {group_7}\n{0x02} 01, {LAR}\n{0x03} 01, {LSL}\n{0x04} 21, {LOADALL?/RESET?/HANG?}\n{0x05} 58, {LOADALL/SYSCALL}\n{0x06} 21, {CLTS}\n{0x07} 36, {LOADALL/SYSRET}\n{0x08} 21, {INVD}\n{0x09} 21, {WBINVD}\n{0x0A} 21, {CL1INVMB}\n{0x0B} 21, {UD1}\n{0x0C} 00, {InvalidOpCode}\n{0x0D} 21, {3DNow}\n{0x0E} 21, {3DNow}\n{0x0F} 21, {3DNow}\n{0x10} 59, {VMOVUPD/VMOVSD/VMOVSS/VMOVUPS}\n{0x11} 59, {VMOVUPD/VMOVSD/VMOVSS/VMOVUPS}\n{0x12} 59, {VMOVLPD/VMOVDDUP/VMOVSLDUP/VMOVLPS/VMOVHLPS}\n{0x13} 60, {InvalidOpCode/VMOVLPD/VMOVLPS}\n{0x14} 60, {InvalidOpCode/VUNPCKLPD/VUNPCKLPS}\n{0x15} 60, {InvalidOpCode/VUNPCKHPD/VUNPCKHPS}\n{0x16} 61, {InvalidOpCode/VMOVHPD/VMOVSHDUP/VMOVLHPS/VMOVHPS}\n{0x17} 60, {InvalidOpCode/VMOVHPD/VMOVHPS}\n{0x18} 62, {group_16}\n{0x19} 62, {group_16}\n{0x1A} 62, {group_16}\n{0x1B} 62, {group_16}\n{0x1C} 62, {group_16}\n{0x1D} 62, {group_16}\n{0x1E} 62, {group_16}\n{0x1F} 62, {group_16}\n{0x20} 63, {MOV}\n{0x21} 63, {MOV}\n{0x22} 63, {MOV}\n{0x23} 63, {MOV}\n{0x24} 63, {MOV}\n{0x25} 00, {InvalidOpCode}\n{0x26} 63, {MOV}\n{0x27} 00, {InvalidOpCode}\n{0x28} 60, {InvalidOpCode/VMOVAPD/VMOVAPS}\n{0x29} 60, {InvalidOpCode/VMOVAPD/VMOVAPS}\n{0x2A} 59, {VCVTSI2SD/CVTPI2PD/VCVTSI2SS/CVTPI2PS}\n{0x2B} 59, {MOVNTSD/MOVNTSS/VMOVNTPD/VMOVNTPS}\n{0x2C} 59, {CVTTPD2PI/VCVTTSD2SI/CVTTPS2PI/VCVTTSS2SI}\n{0x2D} 59, {CVTPD2PI/VCVTSD2SI/CVTPS2PI/VCVTSS2SI}\n{0x2E} 60, {InvalidOpCode/VUCOMISD/VUCOMISS}\n{0x2F} 60, {InvalidOpCode/VCOMISD/VCOMISS}\n{0x30} 21, {WRMSR}\n{0x31} 21, {RDTSC}\n{0x32} 21, {RDMSR}\n{0x33} 21, {RDPMC}\n{0x34} 21, {SYSENTER}\n{0x35} 21, {SYSEXIT}\n{0x36} 00, {InvalidOpCode}\n{0x37} 21, {GETSEC}\n{0x38} 64, {Escape_3_Byte}\n{0x39} 00, {InvalidOpCode}\n{0x3A} 64, {Escape_3_Byte}\n{0x3B} 00, {InvalidOpCode}\n{0x3C} 00, {InvalidOpCode}\n{0x3D} 00, {InvalidOpCode}\n{0x3E} 00, {InvalidOpCode}\n{0x3F} 00, {InvalidOpCode}\n{0x40} 01, {CMOVO}\n{0x41} 01, {CMOVNO}\n{0x42} 01, {CMOVB}\n{0x43} 01, {CMOVNB}\n{0x44} 01, {CMOVZ}\n{0x45} 01, {CMOVNZ}\n{0x46} 01, {CMOVBE}\n{0x47} 01, {CMOVNBE}\n{0x48} 01, {CMOVS}\n{0x49} 01, {CMOVNS}\n{0x4A} 01, {CMOVP}\n{0x4B} 01, {CMOVNP}\n{0x4C} 01, {CMOVL}\n{0x4D} 01, {CMOVNL}\n{0x4E} 01, {CMOVLE}\n{0x4F} 01, {CMOVNLE}\n{0x50} 60, {InvalidOpCode/VMOVMSKPD/VMOVMSKPS}\n{0x51} 59, {VSQRTPD/VSQRTSD/VSQRTSS/VSQRTPS}\n{0x52} 65, {InvalidOpCode/VRSQRTSS/VRSQRTPS}\n{0x53} 65, {InvalidOpCode/VRCPSS/VRCPPS}\n{0x54} 60, {InvalidOpCode/VANDPD/VANDPS}\n{0x55} 60, {InvalidOpCode/VANDNPD/VANDNPS}\n{0x56} 60, {InvalidOpCode/VORPD/VORPS}\n{0x57} 60, {InvalidOpCode/VXORPD/VXORPS}\n{0x58} 59, {VADDPD/VADDSD/VADDSS/VADDPS}\n{0x59} 59, {VMULPD/VMULSD/VMULSS/VMULPS}\n{0x5A} 59, {VCVTPD2PS/VCVTSD2SS/VCVTSS2SD/VCVTPS2PD}\n{0x5B} 61, {InvalidOpCode/VCVTPS2DQ/VCVTTPS2DQ/VCVTDQ2PS}\n{0x5C} 59, {VSUBPD/VSUBSD/VSUBSS/VSUBPS}\n{0x5D} 59, {VMINPD/VMINSD/VMINSS/VMINPS}\n{0x5E} 59, {VDIVPD/VDIVSD/VDIVSS/VDIVPS}\n{0x5F} 59, {VMAXPD/VMAXSD/VMAXSS/VMAXPS}\n{0x60} 60, {PUNPCKLBW/VPUNPCKLBW}\n{0x61} 60, {PUNPCKLWD/VPUNPCKLWD}\n{0x62} 60, {PUNPCKLDQ/VPUNPCKLDQ}\n{0x63} 60, {PACKSSWB/VPACKSSWB}\n{0x64} 60, {PCMPGTB/VPCMPGTB}\n{0x65} 60, {PCMPGTW/VPCMPGTW}\n{0x66} 60, {PCMPGTD/VPCMPGTD}\n{0x67} 60, {PACKUSWB/VPACKUSWB}\n{0x68} 60, {PUNPCKHBW/InvalidOpCode/VPUNPCKHBW}\n{0x69} 60, {PUNPCKHWD/InvalidOpCode/VPUNPCKHWD}\n{0x6A} 60, {PUNPCKHDQ/InvalidOpCode/VPUNPCKHDQ}\n{0x6B} 60, {PACKSSDW/InvalidOpCode/VPACKSSDW}\n{0x6C} 66, {InvalidOpCode/VPUNPCKLQDQ}\n{0x6D} 66, {InvalidOpCode/VPUNPCKHQDQ}\n{0x6E} 60, {MOVDQ/InvalidOpCode/VMOVDQ}\n{0x6F} 61, {MOVQ/InvalidOpCode/VMOVDQA/VMOVDQU}\n{0x70} 67, {VPSHUFD/VPSHUFLW/VPSHUFHW/PSHUFW}\n{0x71} 68, {group_12}\n{0x72} 69, {group_13}\n{0x73} 70, {group_14}\n{0x74} 60, {PCMPEQB/InvalidOpCode/VPCMPEQB}\n{0x75} 60, {PCMPEQW/InvalidOpCode/VPCMPEQW}\n{0x76} 60, {PCMPEQD/InvalidOpCode/VPCMPEQD}\n{0x77} 21, {EMMS/VZEROUPPER/VZEROALL/InvalidOpCode}\n{0x78} 01, {VMREAD/InvalidOpCode}\n{0x79} 01, {VMWRITE/InvalidOpCode}\n{0x7A} 21, {SSE5A/InvalidOpCode}\n{0x7B} 21, {SSE5A/InvalidOpCode}\n{0x7C} 71, {InvalidOpCode/VHADDPD/VHADDPS}\n{0x7D} 71, {InvalidOpCode/VHSUBPD/VHSUBPS}\n{0x7E} 61, {MOVDQ/InvalidOpCode/VMOVDQ/VMOVQ}\n{0x7F} 61, {MOVQ/InvalidOpCode/VMOVDQA/VMOVDQU}\n{0x80} 72, {JO}\n{0x81} 72, {JNO}\n{0x82} 72, {JB}\n{0x83} 72, {JNB}\n{0x84} 72, {JZ}\n{0x85} 72, {JNZ}\n{0x86} 72, {JBE}\n{0x87} 72, {JNBE}\n{0x88} 72, {JS}\n{0x89} 72, {JNS}\n{0x8A} 72, {JP}\n{0x8B} 72, {JNP}\n{0x8C} 72, {JL}\n{0x8D} 72, {JNL}\n{0x8E} 72, {JLE}\n{0x8F} 72, {JNLE}\n{0x90} 01, {SETO}\n{0x91} 01, {SETNO}\n{0x92} 01, {SETB}\n{0x93} 01, {SETNB}\n{0x94} 01, {SETZ}\n{0x95} 01, {SETNZ}\n{0x96} 01, {SETBE}\n{0x97} 01, {SETNBE}\n{0x98} 01, {SETS}\n{0x99} 01, {SETNS}\n{0x9A} 01, {SETP}\n{0x9B} 01, {SETNP}\n{0x9C} 01, {SETL}\n{0x9D} 01, {SETNL}\n{0x9E} 01, {SETLE}\n{0x9F} 01, {SETNLE}\n{0xA0} 11, {PUSH}\n{0xA1} 11, {POP}\n{0xA2} 21, {CPUID}\n{0xA3} 01, {BT}\n{0xA4} 20, {SHLD}\n{0xA5} 01, {SHLD}\n{0xA6} 00, {InvalidOpCode}\n{0xA7} 00, {InvalidOpCode}\n{0xA8} 11, {PUSH}\n{0xA9} 11, {POP}\n{0xAA} 21, {RSM}\n{0xAB} 01, {BTS}\n{0xAC} 20, {SHRD}\n{0xAD} 01, {SHRD}\n{0xAE} 73, {group_15}\n{0xAF} 01, {IMUL}\n{0xB0} 01, {CMPXCHG}\n{0xB1} 01, {CMPXCHG}\n{0xB2} 01, {LSS}\n{0xB3} 01, {BTR}\n{0xB4} 01, {LFS}\n{0xB5} 01, {LGS}\n{0xB6} 01, {MOVZX}\n{0xB7} 01, {MOVZX}\n{0xB8} 74, {POPCNT/InvalidOpCode}\n{0xB9} 75, {group_10_UD2/InvalidOpCode}\n{0xBA} 76, {group_8/InvalidOpCode}\n{0xBB} 01, {BTC/InvalidOpCode}\n{0xBC} 65, {BSF/TZCNT}\n{0xBD} 65, {BSR/LZCNT}\n{0xBE} 01, {MOVSX/InvalidOpCode}\n{0xBF} 01, {MOVSX/InvalidOpCode}\n{0xC0} 59, {XADD}\n{0xC1} 59, {XADD}\n{0xC2} 67, {VCMPccPD/VCMPccSD/VCMPccSS/VCMPccPS}\n{0xC3} 01, {InvalidOpCode/MOVNTI}\n{0xC4} 77, {InvalidOpCode/VPINSRW/PINSRW}\n{0xC5} 77, {InvalidOpCode/VPEXTRW/PEXTRW}\n{0xC6} 77, {InvalidOpCode/VSHUFPD/VSHUFPS}\n{0xC7} 78, {group_9}\n{0xC8} 21, {BSWAP}\n{0xC9} 21, {BSWAP}\n{0xCA} 21, {BSWAP}\n{0xCB} 21, {BSWAP}\n{0xCC} 21, {BSWAP}\n{0xCD} 21, {BSWAP}\n{0xCE} 21, {BSWAP}\n{0xCF} 21, {BSWAP}\n{0xD0} 71, {InvalidOpCode/VADDSUBPD/VADDSUBPS}\n{0xD1} 60, {PSRLW/InvalidOpCode/VPSRLW}\n{0xD2} 60, {PSRLD/InvalidOpCode/VPSRLD}\n{0xD3} 60, {PSRLQ/InvalidOpCode/VPSRLQ}\n{0xD4} 60, {InvalidOpCode/VPADDQ/PADDQ}\n{0xD5} 60, {PMULLW/InvalidOpCode/VPMULLW}\n{0xD6} 79, {InvalidOpCode/MOVDQ2Q/MOVQ2DQ/VMOVQ}\n{0xD7} 60, {InvalidOpCode/VPMOVMSKB/PMOVMSKB}\n{0xD8} 60, {PSUBUSB/VPSUBUSB}\n{0xD9} 60, {PSUBUSW/VPSUBUSW}\n{0xDA} 60, {VPMINUB/PMINUB}\n{0xDB} 60, {PAND/VPAND}\n{0xDC} 60, {PADDUSB/VPADDUSB}\n{0xDD} 60, {PADDUSW/VPADDUSW}\n{0xDE} 60, {VPMAXUB/PMAXUB}\n{0xDF} 60, {PANDN/VPANDN}\n{0xE0} 60, {InvalidOpCode/VPAVGB/PAVGB}\n{0xE1} 60, {PSRAW/InvalidOpCode/VPSRAW}\n{0xE2} 60, {PSRAD/InvalidOpCode/VPSRAD}\n{0xE3} 60, {InvalidOpCode/VPAVGW/PAVGW}\n{0xE4} 60, {InvalidOpCode/VPMULHUW/PMULHUW}\n{0xE5} 60, {PMULHW/InvalidOpCode/VPMULHW}\n{0xE6} 79, {InvalidOpCode/VCVTTPD2DQ/VCVTPD2DQ/VCVTDQ2PD}\n{0xE7} 60, {InvalidOpCode/VMOVNTDQ/MOVNTQ}\n{0xE8} 60, {PSUBSB/VPSUBSB}\n{0xE9} 60, {PSUBSW/VPSUBSW}\n{0xEA} 60, {VPMINSW/PMINSW}\n{0xEB} 60, {POR/VPOR}\n{0xEC} 60, {PADDSB/VPADDSB}\n{0xED} 60, {PADDSW/VPADDSW}\n{0xEE} 60, {VPMAXSW/PMAXSW}\n{0xEF} 60, {PXOR/VPXOR}\n{0xF0} 80, {InvalidOpCode/VLDDQU}\n{0xF1} 60, {PSLLW/InvalidOpCode/VPSLLW}\n{0xF2} 60, {PSLLD/InvalidOpCode/VPSLLD}\n{0xF3} 60, {PSLLQ/InvalidOpCode/VPSLLQ}\n{0xF4} 60, {InvalidOpCode/VPMULUDQ/PMULUDQ}\n{0xF5} 60, {PMADDWD/InvalidOpCode/VPMADDWD}\n{0xF6} 60, {InvalidOpCode/VPSADBW/PSADBW}\n{0xF7} 60, {InvalidOpCode/VMASKMOVDQU/MASKMOVQ}\n{0xF8} 60, {PSUBB/VPSUBB}\n{0xF9} 60, {PSUBW/VPSUBW}\n{0xFA} 60, {PSUBD/VPSUBD}\n{0xFB} 60, {VPSUBQ/PSUBQ}\n{0xFC} 60, {PADDB/VPADDB}\n{0xFD} 60, {PADDW/VPADDW}\n{0xFE} 60, {PADDD/VPADDD}\n{0xFF} 00 {InvalidOpCode}\n);\n{============================================\n                  ThreeByteTable38                    \n============================================}\nconst ThreeByteTable38 : array[Byte] of Byte =(//\n{0x00} 60, {VPSHUFB/PSHUFB}\n{0x01} 60, {VPHADDW/PHADDW}\n{0x02} 60, {VPHADDD/PHADDD}\n{0x03} 60, {VPHADDSW/PHADDSW}\n{0x04} 60, {VPMADDUBSW/PMADDUBSW}\n{0x05} 60, {VPHSUBW/PHSUBW}\n{0x06} 60, {VPHSUBD/PHSUBD}\n{0x07} 60, {VPHSUBSW/PHSUBSW}\n{0x08} 60, {VPSIGNB/PSIGNB}\n{0x09} 60, {VPSIGNW/PSIGNW}\n{0x0A} 60, {VPSIGND/PSIGND}\n{0x0B} 60, {VPMULHRSW/PMULHRSW}\n{0x0C} 66, {VPERMILPS/InvalidOpCode}\n{0x0D} 66, {VPERMILPD/InvalidOpCode}\n{0x0E} 66, {VTESTPS/InvalidOpCode}\n{0x0F} 66, {VTESTPD/InvalidOpCode}\n{0x10} 66, {InvalidOpCode/PBLENDVB}\n{0x11} 00, {InvalidOpCode}\n{0x12} 00, {InvalidOpCode}\n{0x13} 66, {VCVTPH2PS/InvalidOpCode}\n{0x14} 66, {InvalidOpCode/BLENDVPS}\n{0x15} 66, {InvalidOpCode/BLENDVPD}\n{0x16} 66, {VPERMPS/InvalidOpCode}\n{0x17} 66, {InvalidOpCode/VPTEST}\n{0x18} 66, {VBROADCASTSS/InvalidOpCode}\n{0x19} 66, {VBROADCASTSD/InvalidOpCode}\n{0x1A} 66, {VBROADCASTF128/InvalidOpCode}\n{0x1B} 00, {InvalidOpCode}\n{0x1C} 60, {VPABSB/PABSB}\n{0x1D} 60, {VPABSW/PABSW}\n{0x1E} 60, {VPABSD/PABSD}\n{0x1F} 00, {InvalidOpCode}\n{0x20} 66, {InvalidOpCode/VPMOVSXBW}\n{0x21} 66, {InvalidOpCode/VPMOVSXBD}\n{0x22} 66, {InvalidOpCode/VPMOVSXBQ}\n{0x23} 66, {InvalidOpCode/VPMOVSXWD}\n{0x24} 66, {InvalidOpCode/VPMOVSXWQ}\n{0x25} 66, {InvalidOpCode/VPMOVSXDQ}\n{0x26} 00, {InvalidOpCode}\n{0x27} 00, {InvalidOpCode}\n{0x28} 66, {InvalidOpCode/VPMULDQ}\n{0x29} 66, {InvalidOpCode/VPCMPEQQ}\n{0x2A} 66, {InvalidOpCode/VMOVNTDQA}\n{0x2B} 66, {InvalidOpCode/VPACKUSDW}\n{0x2C} 66, {VMASKMOVPS/InvalidOpCode}\n{0x2D} 66, {VMASKMOVPD/InvalidOpCode}\n{0x2E} 66, {VMASKMOVPS/InvalidOpCode}\n{0x2F} 66, {VMASKMOVPD/InvalidOpCode}\n{0x30} 66, {InvalidOpCode/VPMOVZXBW}\n{0x31} 66, {InvalidOpCode/VPMOVZXBD}\n{0x32} 66, {InvalidOpCode/VPMOVZXBQ}\n{0x33} 66, {InvalidOpCode/VPMOVZXWD}\n{0x34} 66, {InvalidOpCode/VPMOVZXWQ}\n{0x35} 66, {InvalidOpCode/VPMOVZXDQ}\n{0x36} 66, {VPERMD/InvalidOpCode}\n{0x37} 66, {InvalidOpCode/VPCMPGTQ}\n{0x38} 66, {InvalidOpCode/VPMINSB}\n{0x39} 66, {InvalidOpCode/VPMINSD}\n{0x3A} 66, {InvalidOpCode/VPMINUW}\n{0x3B} 66, {InvalidOpCode/VPMINUD}\n{0x3C} 66, {InvalidOpCode/VPMAXSB}\n{0x3D} 66, {InvalidOpCode/VPMAXSD}\n{0x3E} 66, {InvalidOpCode/VPMAXUW}\n{0x3F} 66, {InvalidOpCode/VPMAXUD}\n{0x40} 66, {InvalidOpCode/VPMULLD}\n{0x41} 66, {InvalidOpCode/VPHMINPOSUW}\n{0x42} 00, {InvalidOpCode}\n{0x43} 00, {InvalidOpCode}\n{0x44} 00, {InvalidOpCode}\n{0x45} 66, {VPSRLVQ/InvalidOpCode}\n{0x46} 66, {VPSRAVD/InvalidOpCode}\n{0x47} 66, {VPSLLVQ/VPSLLVD/InvalidOpCode}\n{0x48} 00, {InvalidOpCode}\n{0x49} 00, {InvalidOpCode}\n{0x4A} 00, {InvalidOpCode}\n{0x4B} 00, {InvalidOpCode}\n{0x4C} 00, {InvalidOpCode}\n{0x4D} 00, {InvalidOpCode}\n{0x4E} 00, {InvalidOpCode}\n{0x4F} 00, {InvalidOpCode}\n{0x50} 00, {InvalidOpCode}\n{0x51} 00, {InvalidOpCode}\n{0x52} 00, {InvalidOpCode}\n{0x53} 00, {InvalidOpCode}\n{0x54} 00, {InvalidOpCode}\n{0x55} 00, {InvalidOpCode}\n{0x56} 00, {InvalidOpCode}\n{0x57} 00, {InvalidOpCode}\n{0x58} 66, {VPBROADCASTD/InvalidOpCode}\n{0x59} 66, {VPBROADCASTQ/InvalidOpCode}\n{0x5A} 66, {VBROADCASTI128/InvalidOpCode}\n{0x5B} 00, {InvalidOpCode}\n{0x5C} 00, {InvalidOpCode}\n{0x5D} 00, {InvalidOpCode}\n{0x5E} 00, {InvalidOpCode}\n{0x5F} 00, {InvalidOpCode}\n{0x60} 00, {InvalidOpCode}\n{0x61} 00, {InvalidOpCode}\n{0x62} 00, {InvalidOpCode}\n{0x63} 00, {InvalidOpCode}\n{0x64} 00, {InvalidOpCode}\n{0x65} 00, {InvalidOpCode}\n{0x66} 00, {InvalidOpCode}\n{0x67} 00, {InvalidOpCode}\n{0x68} 00, {InvalidOpCode}\n{0x69} 00, {InvalidOpCode}\n{0x6A} 00, {InvalidOpCode}\n{0x6B} 00, {InvalidOpCode}\n{0x6C} 00, {InvalidOpCode}\n{0x6D} 00, {InvalidOpCode}\n{0x6E} 00, {InvalidOpCode}\n{0x6F} 00, {InvalidOpCode}\n{0x70} 00, {InvalidOpCode}\n{0x71} 00, {InvalidOpCode}\n{0x72} 00, {InvalidOpCode}\n{0x73} 00, {InvalidOpCode}\n{0x74} 00, {InvalidOpCode}\n{0x75} 00, {InvalidOpCode}\n{0x76} 00, {InvalidOpCode}\n{0x77} 00, {InvalidOpCode}\n{0x78} 66, {VPBROADCASTB/InvalidOpCode}\n{0x79} 66, {VPBROADCASTW/InvalidOpCode}\n{0x7A} 00, {InvalidOpCode}\n{0x7B} 00, {InvalidOpCode}\n{0x7C} 00, {InvalidOpCode}\n{0x7D} 00, {InvalidOpCode}\n{0x7E} 00, {InvalidOpCode}\n{0x7F} 00, {InvalidOpCode}\n{0x80} 66, {INVPCID}\n{0x81} 66, {INVVPID}\n{0x82} 66, {INVPCID}\n{0x83} 00, {InvalidOpCode}\n{0x84} 00, {InvalidOpCode}\n{0x85} 00, {InvalidOpCode}\n{0x86} 00, {InvalidOpCode}\n{0x87} 00, {InvalidOpCode}\n{0x88} 00, {InvalidOpCode}\n{0x89} 00, {InvalidOpCode}\n{0x8A} 00, {InvalidOpCode}\n{0x8B} 00, {InvalidOpCode}\n{0x8C} 66, {VPMASKMOVD/VPMASKMOVQ/InvalidOpCode}\n{0x8D} 00, {InvalidOpCode}\n{0x8E} 66, {VPMASKMOVD/VPMASKMOVQ/InvalidOpCode}\n{0x8F} 00, {InvalidOpCode}\n{0x90} 66, {VPGATHERDD/VPGATHERDQ}\n{0x91} 66, {VPGATHERQD/VPGATHERQQ}\n{0x92} 66, {VGATHERDPS/VGATHERDPD}\n{0x93} 66, {VGATHERQPS/VGATHERQPD}\n{0x94} 00, {InvalidOpCode}\n{0x95} 00, {InvalidOpCode}\n{0x96} 66, {VFMADDSUB132PS/VFMADDSUB132PD}\n{0x97} 66, {VFMSUBADD132PS/VFMSUBADD132PD}\n{0x98} 66, {VFMADD132PS/VFMADD132PD}\n{0x99} 66, {VFMADD132SS/VFMADD132SD}\n{0x9A} 66, {VFMSUB132PS/VFMSUB132PD}\n{0x9B} 66, {VFMSUB132SS/VFMSUB132SD}\n{0x9C} 66, {VFNMADD132PS/VFNMADD132PD}\n{0x9D} 66, {VFNMADD132SS/VFNMADD132SD}\n{0x9E} 66, {VFNMSUB132PS/VFNMSUB132PD}\n{0x9F} 66, {VFNMSUB132SS/VFNMSUB132SD}\n{0xA0} 00, {InvalidOpCode}\n{0xA1} 00, {InvalidOpCode}\n{0xA2} 00, {InvalidOpCode}\n{0xA3} 00, {InvalidOpCode}\n{0xA4} 00, {InvalidOpCode}\n{0xA5} 00, {InvalidOpCode}\n{0xA6} 66, {VFMADDSUB213PS/VFMADDSUB213PD}\n{0xA7} 66, {VFMSUBADD213PS/VFMSUBADD213PD}\n{0xA8} 66, {VFMADD213PS/VFMADD213PD}\n{0xA9} 66, {VFMADD213SS/VFMADD213SD}\n{0xAA} 66, {VFMSUB213PS/VFMSUB213PD}\n{0xAB} 66, {VFMSUB213SS/VFMSUB213SD}\n{0xAC} 66, {VFNMADD213PS/VFNMADD213PD}\n{0xAD} 66, {VFNMADD213SS/VFNMADD213SD}\n{0xAE} 66, {VFNMSUB213PS/VFNMSUB213PD}\n{0xAF} 66, {VFNMSUB213SS/VFNMSUB213SD}\n{0xB0} 00, {InvalidOpCode}\n{0xB1} 00, {InvalidOpCode}\n{0xB2} 00, {InvalidOpCode}\n{0xB3} 00, {InvalidOpCode}\n{0xB4} 00, {InvalidOpCode}\n{0xB5} 00, {InvalidOpCode}\n{0xB6} 66, {VFMADDSUB231PS/VFMADDSUB231PD}\n{0xB7} 66, {VFMSUBADD231PS/VFMSUBADD231PD}\n{0xB8} 66, {VFMADD231PS/VFMADD231PD}\n{0xB9} 66, {VFMADD231SS/VFMADD231SD}\n{0xBA} 66, {VFMSUB231PS/VFMSUB231PD}\n{0xBB} 66, {VFMSUB231SS/VFMSUB231SD}\n{0xBC} 66, {VFNMADD231PS/VFNMADD231PD}\n{0xBD} 66, {VFNMADD231SS/VFNMADD231SD}\n{0xBE} 66, {VFNMSUB231PS/VFNMSUB231PD}\n{0xBF} 66, {VFNMSUB231SS/VFNMSUB231SD}\n{0xC0} 00, {InvalidOpCode}\n{0xC1} 00, {InvalidOpCode}\n{0xC2} 00, {InvalidOpCode}\n{0xC3} 00, {InvalidOpCode}\n{0xC4} 00, {InvalidOpCode}\n{0xC5} 00, {InvalidOpCode}\n{0xC6} 00, {InvalidOpCode}\n{0xC7} 00, {InvalidOpCode}\n{0xC8} 01, {SHA1NEXTE}\n{0xC9} 01, {SHA1MSG1}\n{0xCA} 01, {SHA1MSG2}\n{0xCB} 01, {SHA256RNDS2}\n{0xCC} 01, {SHA256MSG1}\n{0xCD} 01, {SHA256MSG2}\n{0xCE} 00, {InvalidOpCode}\n{0xCF} 00, {InvalidOpCode}\n{0xD0} 00, {InvalidOpCode}\n{0xD1} 00, {InvalidOpCode}\n{0xD2} 00, {InvalidOpCode}\n{0xD3} 00, {InvalidOpCode}\n{0xD4} 00, {InvalidOpCode}\n{0xD5} 00, {InvalidOpCode}\n{0xD6} 00, {InvalidOpCode}\n{0xD7} 00, {InvalidOpCode}\n{0xD8} 00, {InvalidOpCode}\n{0xD9} 00, {InvalidOpCode}\n{0xDA} 00, {InvalidOpCode}\n{0xDB} 66, {VAESIMC}\n{0xDC} 66, {VAESENC}\n{0xDD} 66, {VAESENCLAST}\n{0xDE} 66, {VAESDEC}\n{0xDF} 66, {VAESDECLAST}\n{0xE0} 00, {InvalidOpCode}\n{0xE1} 00, {InvalidOpCode}\n{0xE2} 00, {InvalidOpCode}\n{0xE3} 00, {InvalidOpCode}\n{0xE4} 00, {InvalidOpCode}\n{0xE5} 00, {InvalidOpCode}\n{0xE6} 00, {InvalidOpCode}\n{0xE7} 00, {InvalidOpCode}\n{0xE8} 00, {InvalidOpCode}\n{0xE9} 00, {InvalidOpCode}\n{0xEA} 00, {InvalidOpCode}\n{0xEB} 00, {InvalidOpCode}\n{0xEC} 00, {InvalidOpCode}\n{0xED} 00, {InvalidOpCode}\n{0xEE} 00, {InvalidOpCode}\n{0xEF} 00, {InvalidOpCode}\n{0xF0} 81, {MOVBE/InvalidOpCode/CRC32}\n{0xF1} 81, {MOVBE/InvalidOpCode/CRC32}\n{0xF2} 81, {ANDNv/InvalidOpCode}\n{0xF3} 81, {group_17}\n{0xF4} 81, {InvalidOpCode}\n{0xF5} 81, {PDEPv/PEXTv/BZHIv/InvalidOpCode}\n{0xF6} 81, {MULXv/ADCX/ADOX/InvalidOpCode}\n{0xF7} 81, {SHLXv/SHRXv/SARXv/BEXTRv/InvalidOpCode}\n{0xF8} 00, {InvalidOpCode}\n{0xF9} 00, {InvalidOpCode}\n{0xFA} 00, {InvalidOpCode}\n{0xFB} 00, {InvalidOpCode}\n{0xFC} 00, {InvalidOpCode}\n{0xFD} 00, {InvalidOpCode}\n{0xFE} 00, {InvalidOpCode}\n{0xFF} 00 {InvalidOpCode}\n);\n{============================================\n                  ThreeByteTable3A                    \n============================================}\nconst ThreeByteTable3A : array[Byte] of Byte =(//\n{0x00} 82, {VPERMQ/InvalidOpCode}\n{0x01} 82, {VPERMPD/InvalidOpCode}\n{0x02} 82, {VPBLENDD/InvalidOpCode}\n{0x03} 00, {InvalidOpCode}\n{0x04} 82, {VPERMILPS/InvalidOpCode}\n{0x05} 82, {VPERMILPD/InvalidOpCode}\n{0x06} 82, {VPERM2F128/InvalidOpCode}\n{0x07} 00, {InvalidOpCode}\n{0x08} 82, {InvalidOpCode/VROUNDPS}\n{0x09} 82, {InvalidOpCode/VROUNDPD}\n{0x0A} 82, {InvalidOpCode/VROUNDSS}\n{0x0B} 82, {InvalidOpCode/VROUNDSD}\n{0x0C} 82, {InvalidOpCode/VBLENDPS}\n{0x0D} 82, {InvalidOpCode/VBLENDPD}\n{0x0E} 82, {InvalidOpCode/VPBLENDW}\n{0x0F} 77, {VPALIGNR/PALIGNR}\n{0x10} 00, {InvalidOpCode}\n{0x11} 00, {InvalidOpCode}\n{0x12} 00, {InvalidOpCode}\n{0x13} 00, {InvalidOpCode}\n{0x14} 82, {InvalidOpCode/VPEXTRB}\n{0x15} 82, {InvalidOpCode/VPEXTRW}\n{0x16} 82, {InvalidOpCode/VPEXTRD}\n{0x17} 82, {InvalidOpCode/VEXTRACTPS}\n{0x18} 82, {VINSERTF128/InvalidOpCode}\n{0x19} 82, {VEXTRACTF128/InvalidOpCode}\n{0x1A} 00, {InvalidOpCode}\n{0x1B} 00, {InvalidOpCode}\n{0x1C} 00, {InvalidOpCode}\n{0x1D} 82, {VCVTPS2PH/InvalidOpCode}\n{0x1E} 00, {InvalidOpCode}\n{0x1F} 00, {InvalidOpCode}\n{0x20} 82, {InvalidOpCode/VINSERTPS}\n{0x21} 82, {InvalidOpCode/VPINSRD}\n{0x22} 00, {InvalidOpCode}\n{0x23} 00, {InvalidOpCode}\n{0x24} 00, {InvalidOpCode}\n{0x25} 00, {InvalidOpCode}\n{0x26} 00, {InvalidOpCode}\n{0x27} 00, {InvalidOpCode}\n{0x28} 00, {InvalidOpCode}\n{0x29} 00, {InvalidOpCode}\n{0x2A} 00, {InvalidOpCode}\n{0x2B} 00, {InvalidOpCode}\n{0x2C} 00, {InvalidOpCode}\n{0x2D} 00, {InvalidOpCode}\n{0x2E} 00, {InvalidOpCode}\n{0x2F} 00, {InvalidOpCode}\n{0x30} 00, {InvalidOpCode}\n{0x31} 00, {InvalidOpCode}\n{0x32} 00, {InvalidOpCode}\n{0x33} 00, {InvalidOpCode}\n{0x34} 00, {InvalidOpCode}\n{0x35} 00, {InvalidOpCode}\n{0x36} 00, {InvalidOpCode}\n{0x37} 00, {InvalidOpCode}\n{0x38} 82, {VINSERTI128/InvalidOpCode}\n{0x39} 82, {VEXTRACTI128/InvalidOpCode}\n{0x3A} 00, {InvalidOpCode}\n{0x3B} 00, {InvalidOpCode}\n{0x3C} 00, {InvalidOpCode}\n{0x3D} 00, {InvalidOpCode}\n{0x3E} 00, {InvalidOpCode}\n{0x3F} 00, {InvalidOpCode}\n{0x40} 82, {InvalidOpCode/VDPPS}\n{0x41} 82, {InvalidOpCode/VDPPD}\n{0x42} 82, {InvalidOpCode/VMPSADBW}\n{0x43} 00, {InvalidOpCode}\n{0x44} 82, {InvalidOpCode/VPCLMULQDQ}\n{0x45} 00, {InvalidOpCode}\n{0x46} 82, {VPERM2I128/InvalidOpCode}\n{0x47} 00, {InvalidOpCode}\n{0x48} 82, {VPERMILzz2PS/InvalidOpCode}\n{0x49} 82, {VPERMILzz2PD/InvalidOpCode}\n{0x4A} 66, {VBLENDVPS/InvalidOpCode}\n{0x4B} 66, {VBLENDVPD/InvalidOpCode}\n{0x4C} 66, {VPBLENDVB/InvalidOpCode}\n{0x4D} 00, {InvalidOpCode}\n{0x4E} 00, {InvalidOpCode}\n{0x4F} 00, {InvalidOpCode}\n{0x50} 00, {InvalidOpCode}\n{0x51} 00, {InvalidOpCode}\n{0x52} 00, {InvalidOpCode}\n{0x53} 00, {InvalidOpCode}\n{0x54} 00, {InvalidOpCode}\n{0x55} 00, {InvalidOpCode}\n{0x56} 00, {InvalidOpCode}\n{0x57} 00, {InvalidOpCode}\n{0x58} 00, {InvalidOpCode}\n{0x59} 00, {InvalidOpCode}\n{0x5A} 00, {InvalidOpCode}\n{0x5B} 00, {InvalidOpCode}\n{0x5C} 66, {VFMADDSUBPS/InvalidOpCode}\n{0x5D} 66, {VFMADDSUBPD/InvalidOpCode}\n{0x5E} 66, {VFMSUBADDPS/InvalidOpCode}\n{0x5F} 66, {VFMSUBADDPD/InvalidOpCode}\n{0x60} 82, {InvalidOpCode/VPCMPESTRM}\n{0x61} 82, {InvalidOpCode/VPCMPESTRI}\n{0x62} 82, {InvalidOpCode/VPCMPISTRM}\n{0x63} 82, {InvalidOpCode/VPCMPISTRI}\n{0x64} 00, {InvalidOpCode}\n{0x65} 00, {InvalidOpCode}\n{0x66} 00, {InvalidOpCode}\n{0x67} 00, {InvalidOpCode}\n{0x68} 66, {VFMADDPS/InvalidOpCode}\n{0x69} 66, {VFMADDPD/InvalidOpCode}\n{0x6A} 66, {VFMADDSS/InvalidOpCode}\n{0x6B} 66, {VFMADDSD/InvalidOpCode}\n{0x6C} 66, {VFMSUBPS/InvalidOpCode}\n{0x6D} 66, {VFMSUBPD/InvalidOpCode}\n{0x6E} 66, {VFMSUBSS/InvalidOpCode}\n{0x6F} 66, {VFMSUBSD/InvalidOpCode}\n{0x70} 00, {InvalidOpCode}\n{0x71} 00, {InvalidOpCode}\n{0x72} 00, {InvalidOpCode}\n{0x73} 00, {InvalidOpCode}\n{0x74} 00, {InvalidOpCode}\n{0x75} 00, {InvalidOpCode}\n{0x76} 00, {InvalidOpCode}\n{0x77} 00, {InvalidOpCode}\n{0x78} 66, {VFNMADDPS/InvalidOpCode}\n{0x79} 66, {VFNMADDPD/InvalidOpCode}\n{0x7A} 66, {VFNMADDSS/InvalidOpCode}\n{0x7B} 66, {VFNMADDSD/InvalidOpCode}\n{0x7C} 66, {VFNMSUBPS/InvalidOpCode}\n{0x7D} 66, {VFNMSUBPD/InvalidOpCode}\n{0x7E} 66, {VFNMSUBSS/InvalidOpCode}\n{0x7F} 66, {VFNMSUBSD/InvalidOpCode}\n{0x80} 00, {InvalidOpCode}\n{0x81} 00, {InvalidOpCode}\n{0x82} 00, {InvalidOpCode}\n{0x83} 00, {InvalidOpCode}\n{0x84} 00, {InvalidOpCode}\n{0x85} 00, {InvalidOpCode}\n{0x86} 00, {InvalidOpCode}\n{0x87} 00, {InvalidOpCode}\n{0x88} 00, {InvalidOpCode}\n{0x89} 00, {InvalidOpCode}\n{0x8A} 00, {InvalidOpCode}\n{0x8B} 00, {InvalidOpCode}\n{0x8C} 00, {InvalidOpCode}\n{0x8D} 00, {InvalidOpCode}\n{0x8E} 00, {InvalidOpCode}\n{0x8F} 00, {InvalidOpCode}\n{0x90} 00, {InvalidOpCode}\n{0x91} 00, {InvalidOpCode}\n{0x92} 00, {InvalidOpCode}\n{0x93} 00, {InvalidOpCode}\n{0x94} 00, {InvalidOpCode}\n{0x95} 00, {InvalidOpCode}\n{0x96} 00, {InvalidOpCode}\n{0x97} 00, {InvalidOpCode}\n{0x98} 00, {InvalidOpCode}\n{0x99} 00, {InvalidOpCode}\n{0x9A} 00, {InvalidOpCode}\n{0x9B} 00, {InvalidOpCode}\n{0x9C} 00, {InvalidOpCode}\n{0x9D} 00, {InvalidOpCode}\n{0x9E} 00, {InvalidOpCode}\n{0x9F} 00, {InvalidOpCode}\n{0xA0} 00, {InvalidOpCode}\n{0xA1} 00, {InvalidOpCode}\n{0xA2} 00, {InvalidOpCode}\n{0xA3} 00, {InvalidOpCode}\n{0xA4} 00, {InvalidOpCode}\n{0xA5} 00, {InvalidOpCode}\n{0xA6} 00, {InvalidOpCode}\n{0xA7} 00, {InvalidOpCode}\n{0xA8} 00, {InvalidOpCode}\n{0xA9} 00, {InvalidOpCode}\n{0xAA} 00, {InvalidOpCode}\n{0xAB} 00, {InvalidOpCode}\n{0xAC} 00, {InvalidOpCode}\n{0xAD} 00, {InvalidOpCode}\n{0xAE} 00, {InvalidOpCode}\n{0xAF} 00, {InvalidOpCode}\n{0xB0} 00, {InvalidOpCode}\n{0xB1} 00, {InvalidOpCode}\n{0xB2} 00, {InvalidOpCode}\n{0xB3} 00, {InvalidOpCode}\n{0xB4} 00, {InvalidOpCode}\n{0xB5} 00, {InvalidOpCode}\n{0xB6} 00, {InvalidOpCode}\n{0xB7} 00, {InvalidOpCode}\n{0xB8} 00, {InvalidOpCode}\n{0xB9} 00, {InvalidOpCode}\n{0xBA} 00, {InvalidOpCode}\n{0xBB} 00, {InvalidOpCode}\n{0xBC} 00, {InvalidOpCode}\n{0xBD} 00, {InvalidOpCode}\n{0xBE} 00, {InvalidOpCode}\n{0xBF} 00, {InvalidOpCode}\n{0xC0} 00, {InvalidOpCode}\n{0xC1} 00, {InvalidOpCode}\n{0xC2} 00, {InvalidOpCode}\n{0xC3} 00, {InvalidOpCode}\n{0xC4} 00, {InvalidOpCode}\n{0xC5} 00, {InvalidOpCode}\n{0xC6} 00, {InvalidOpCode}\n{0xC7} 00, {InvalidOpCode}\n{0xC8} 00, {InvalidOpCode}\n{0xC9} 00, {InvalidOpCode}\n{0xCA} 00, {InvalidOpCode}\n{0xCB} 00, {InvalidOpCode}\n{0xCC} 20, {SHA1RNDS4}\n{0xCD} 00, {InvalidOpCode}\n{0xCE} 00, {InvalidOpCode}\n{0xCF} 00, {InvalidOpCode}\n{0xD0} 00, {InvalidOpCode}\n{0xD1} 00, {InvalidOpCode}\n{0xD2} 00, {InvalidOpCode}\n{0xD3} 00, {InvalidOpCode}\n{0xD4} 00, {InvalidOpCode}\n{0xD5} 00, {InvalidOpCode}\n{0xD6} 00, {InvalidOpCode}\n{0xD7} 00, {InvalidOpCode}\n{0xD8} 00, {InvalidOpCode}\n{0xD9} 00, {InvalidOpCode}\n{0xDA} 00, {InvalidOpCode}\n{0xDB} 00, {InvalidOpCode}\n{0xDC} 00, {InvalidOpCode}\n{0xDD} 00, {InvalidOpCode}\n{0xDE} 00, {InvalidOpCode}\n{0xDF} 82, {VAESKEYGENASSIST}\n{0xE0} 00, {InvalidOpCode}\n{0xE1} 00, {InvalidOpCode}\n{0xE2} 00, {InvalidOpCode}\n{0xE3} 00, {InvalidOpCode}\n{0xE4} 00, {InvalidOpCode}\n{0xE5} 00, {InvalidOpCode}\n{0xE6} 00, {InvalidOpCode}\n{0xE7} 00, {InvalidOpCode}\n{0xE8} 00, {InvalidOpCode}\n{0xE9} 00, {InvalidOpCode}\n{0xEA} 00, {InvalidOpCode}\n{0xEB} 00, {InvalidOpCode}\n{0xEC} 00, {InvalidOpCode}\n{0xED} 00, {InvalidOpCode}\n{0xEE} 00, {InvalidOpCode}\n{0xEF} 00, {InvalidOpCode}\n{0xF0} 83, {RORXv}\n{0xF1} 00, {InvalidOpCode}\n{0xF2} 00, {InvalidOpCode}\n{0xF3} 00, {InvalidOpCode}\n{0xF4} 00, {InvalidOpCode}\n{0xF5} 00, {InvalidOpCode}\n{0xF6} 00, {InvalidOpCode}\n{0xF7} 00, {InvalidOpCode}\n{0xF8} 00, {InvalidOpCode}\n{0xF9} 00, {InvalidOpCode}\n{0xFA} 00, {InvalidOpCode}\n{0xFB} 00, {InvalidOpCode}\n{0xFC} 00, {InvalidOpCode}\n{0xFD} 00, {InvalidOpCode}\n{0xFE} 00, {InvalidOpCode}\n{0xFF} 00 {InvalidOpCode}\n);\n"
  },
  {
    "path": "Source/TlHelp32.inc",
    "content": "{ TlHelp32 types for fpc }\n\nconst\n  TH32CS_SNAPHEAPLIST = $00000001;\n  TH32CS_SNAPPROCESS  = $00000002;\n  TH32CS_SNAPTHREAD   = $00000004;\n  TH32CS_SNAPMODULE   = $00000008;\n  TH32CS_SNAPALL      = TH32CS_SNAPHEAPLIST or TH32CS_SNAPPROCESS or\n    TH32CS_SNAPTHREAD or TH32CS_SNAPMODULE;\n  TH32CS_INHERIT      = $80000000;\n\n  TLS_OUT_OF_INDEXES = DWORD($FFFFFFFF);  // FPC does not declare TLS_OUT_OF_INDEXES.\n\ntype \n tagTHREADENTRY32 = record\n    dwSize: DWORD;\n    cntUsage: DWORD;\n    th32ThreadID: DWORD;       \n    th32OwnerProcessID: DWORD; \n    tpBasePri: Longint;\n    tpDeltaPri: Longint;\n    dwFlags: DWORD;\n  end;\n  THREADENTRY32 = tagTHREADENTRY32;\n  PTHREADENTRY32 = ^tagTHREADENTRY32;\n  LPTHREADENTRY32 = ^tagTHREADENTRY32;\n  TThreadEntry32 = tagTHREADENTRY32;\n\n  TThread32First = function (hSnapshot: THandle; var lpte: TThreadEntry32): BOOL stdcall;\n  TThread32Next = function (hSnapshot: THandle; var lpte: TThreadENtry32): BOOL stdcall;\n  TCreateToolhelp32Snapshot = function (dwFlags, th32ProcessID: DWORD): THandle; stdcall;  \n"
  },
  {
    "path": "Test/Test.dpr",
    "content": "program Test;\n\n{$IFNDEF TESTINSIGHT}\n{$APPTYPE CONSOLE}\n{$ENDIF}{$STRONGLINKTYPES ON}\nuses\n  System.SysUtils,\n  {$IFDEF TESTINSIGHT}\n  TestInsight.DUnitX,\n  {$ENDIF }\n  DUnitX.Loggers.Console,\n  DUnitX.Loggers.Xml.NUnit,\n  DUnitX.TestFramework,\n  uTest in 'uTest.pas';\n\nvar\n  runner : ITestRunner;\n  results : IRunResults;\n  logger : ITestLogger;\n  nunitLogger : ITestLogger;\nbegin\n{$IFDEF TESTINSIGHT}\n  TestInsight.DUnitX.RunRegisteredTests;\n  exit;\n{$ENDIF}\n  try\n    //Check command line options, will exit if invalid\n    TDUnitX.CheckCommandLine;\n    //Create the test runner\n    runner := TDUnitX.CreateRunner;\n    //Tell the runner to use RTTI to find Fixtures\n    runner.UseRTTI := True;\n    //tell the runner how we will log things\n    //Log to the console window\n    logger := TDUnitXConsoleLogger.Create(true);\n    runner.AddLogger(logger);\n    //Generate an NUnit compatible XML File\n    nunitLogger := TDUnitXXMLNUnitFileLogger.Create(TDUnitX.Options.XMLOutputFile);\n    runner.AddLogger(nunitLogger);\n    runner.FailsOnNoAsserts := False; //When true, Assertions must be made during tests;\n\n    //Run tests\n    results := runner.Execute;\n    if not results.AllPassed then\n      System.ExitCode := EXIT_ERRORS;\n\n    {$IFNDEF CI}\n    //We don't want this happening when running under CI.\n    if TDUnitX.Options.ExitBehavior = TDUnitXExitBehavior.Pause then\n    begin\n      System.Write('Done.. press <Enter> key to quit.');\n      System.Readln;\n    end;\n    {$ENDIF}\n  except\n    on E: Exception do\n      System.Writeln(E.ClassName, ': ', E.Message);\n  end;\nend.\n"
  },
  {
    "path": "Test/Test.dproj",
    "content": "﻿<Project xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n    <PropertyGroup>\n        <ProjectGuid>{AE7FD8B6-27D8-45EA-B53E-B9F470DA9BA0}</ProjectGuid>\n        <ProjectVersion>18.7</ProjectVersion>\n        <FrameworkType>None</FrameworkType>\n        <MainSource>Test.dpr</MainSource>\n        <Base>True</Base>\n        <Config Condition=\"'$(Config)'==''\">Debug</Config>\n        <Platform Condition=\"'$(Platform)'==''\">Win32</Platform>\n        <TargetedPlatforms>3</TargetedPlatforms>\n        <AppType>Console</AppType>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"'$(Config)'=='Base' or '$(Base)'!=''\">\n        <Base>true</Base>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"('$(Platform)'=='Android' and '$(Base)'=='true') or '$(Base_Android)'!=''\">\n        <Base_Android>true</Base_Android>\n        <CfgParent>Base</CfgParent>\n        <Base>true</Base>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''\">\n        <Base_Win32>true</Base_Win32>\n        <CfgParent>Base</CfgParent>\n        <Base>true</Base>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"('$(Platform)'=='Win64' and '$(Base)'=='true') or '$(Base_Win64)'!=''\">\n        <Base_Win64>true</Base_Win64>\n        <CfgParent>Base</CfgParent>\n        <Base>true</Base>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"'$(Config)'=='Debug' or '$(Cfg_1)'!=''\">\n        <Cfg_1>true</Cfg_1>\n        <CfgParent>Base</CfgParent>\n        <Base>true</Base>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"('$(Platform)'=='Win32' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win32)'!=''\">\n        <Cfg_1_Win32>true</Cfg_1_Win32>\n        <CfgParent>Cfg_1</CfgParent>\n        <Cfg_1>true</Cfg_1>\n        <Base>true</Base>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"'$(Config)'=='Release' or '$(Cfg_2)'!=''\">\n        <Cfg_2>true</Cfg_2>\n        <CfgParent>Base</CfgParent>\n        <Base>true</Base>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"'$(Base)'!=''\">\n        <DCC_DcuOutput>.\\$(Platform)\\$(Config)</DCC_DcuOutput>\n        <DCC_ExeOutput>.\\$(Platform)\\$(Config)</DCC_ExeOutput>\n        <DCC_E>false</DCC_E>\n        <DCC_N>false</DCC_N>\n        <DCC_S>false</DCC_S>\n        <DCC_F>false</DCC_F>\n        <DCC_K>false</DCC_K>\n        <DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)</DCC_Namespace>\n        <Icon_MainIcon>$(BDS)\\bin\\delphi_PROJECTICON.ico</Icon_MainIcon>\n        <Icns_MainIcns>$(BDS)\\bin\\delphi_PROJECTICNS.icns</Icns_MainIcns>\n        <DCC_UnitSearchPath>$(DUnitX);$(DCC_UnitSearchPath)</DCC_UnitSearchPath>\n        <SanitizedProjectName>Test</SanitizedProjectName>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"'$(Base_Android)'!=''\">\n        <DCC_UsePackage>DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;IndyIPServer;IndySystem;tethering;fmxFireDAC;FireDAC;bindcompfmx;FireDACSqliteDriver;ibmonitor;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;xmlrtl;soapmidas;ibxbindings;rtl;DbxClientDriver;CustomIPTransport;dbexpress;IndyCore;bindcomp;dsnap;FireDACCommon;IndyIPClient;RESTBackendComponents;soapserver;dbxcds;bindengine;CloudService;dsnapxml;dbrtl;IndyProtocols;FireDACCommonDriver;inet;$(DCC_UsePackage)</DCC_UsePackage>\n        <EnabledSysJars>android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar</EnabledSysJars>\n        <VerInfo_Keys>package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=</VerInfo_Keys>\n        <BT_BuildType>Debug</BT_BuildType>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"'$(Base_Win32)'!=''\">\n        <DCC_UsePackage>DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;StyleControls_dxe103Rio;vclFireDAC;IndySystem;tethering;svnui;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;svn;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;FMXTee;MyIdePlugin;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;dclAbsDBd26;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;bindcomp;appanalytics;dsnap;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;vclAbsDBd26;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)</DCC_UsePackage>\n        <DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>\n        <BT_BuildType>Debug</BT_BuildType>\n        <VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>\n        <VerInfo_Locale>1033</VerInfo_Locale>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"'$(Base_Win64)'!=''\">\n        <DCC_UsePackage>DBXSqliteDriver;IndyIPCommon;RESTComponents;bindcompdbx;DBXInterBaseDriver;vcl;IndyIPServer;vclactnband;StyleControls_dxe103Rio;vclFireDAC;IndySystem;tethering;dsnapcon;FireDACADSDriver;FireDACMSAccDriver;fmxFireDAC;vclimg;TeeDB;FireDAC;vcltouch;vcldb;bindcompfmx;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;inetdb;FMXTee;soaprtl;DbxCommonDriver;FmxTeeUI;ibxpress;fmx;FireDACIBDriver;fmxdae;xmlrtl;soapmidas;ibxbindings;fmxobj;vclwinx;vclib;rtl;Tee;DbxClientDriver;CustomIPTransport;vcldsnap;dbexpress;IndyCore;vclx;bindcomp;appanalytics;dsnap;FireDACCommon;IndyIPClient;bindcompvcl;RESTBackendComponents;TeeUI;VCLRESTComponents;soapserver;dbxcds;VclSmp;adortl;vclie;bindengine;DBXMySQLDriver;CloudService;dsnapxml;FireDACMySQLDriver;dbrtl;IndyProtocols;inetdbxpress;FireDACCommonODBC;FireDACCommonDriver;inet;fmxase;$(DCC_UsePackage)</DCC_UsePackage>\n        <DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)</DCC_Namespace>\n        <BT_BuildType>Debug</BT_BuildType>\n        <VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>\n        <VerInfo_Locale>1033</VerInfo_Locale>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"'$(Cfg_1)'!=''\">\n        <DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>\n        <DCC_DebugDCUs>true</DCC_DebugDCUs>\n        <DCC_Optimize>false</DCC_Optimize>\n        <DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>\n        <DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>\n        <DCC_RemoteDebug>true</DCC_RemoteDebug>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"'$(Cfg_1_Win32)'!=''\">\n        <DCC_RemoteDebug>false</DCC_RemoteDebug>\n    </PropertyGroup>\n    <PropertyGroup Condition=\"'$(Cfg_2)'!=''\">\n        <DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>\n        <DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>\n        <DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>\n        <DCC_DebugInformation>0</DCC_DebugInformation>\n    </PropertyGroup>\n    <ItemGroup>\n        <DelphiCompile Include=\"$(MainSource)\">\n            <MainSource>MainSource</MainSource>\n        </DelphiCompile>\n        <DCCReference Include=\"uTest.pas\"/>\n        <BuildConfiguration Include=\"Release\">\n            <Key>Cfg_2</Key>\n            <CfgParent>Base</CfgParent>\n        </BuildConfiguration>\n        <BuildConfiguration Include=\"Base\">\n            <Key>Base</Key>\n        </BuildConfiguration>\n        <BuildConfiguration Include=\"Debug\">\n            <Key>Cfg_1</Key>\n            <CfgParent>Base</CfgParent>\n        </BuildConfiguration>\n    </ItemGroup>\n    <ProjectExtensions>\n        <Borland.Personality>Delphi.Personality.12</Borland.Personality>\n        <Borland.ProjectType>Console</Borland.ProjectType>\n        <BorlandProject>\n            <Delphi.Personality>\n                <Source>\n                    <Source Name=\"MainSource\">Test.dpr</Source>\n                </Source>\n            </Delphi.Personality>\n            <Deployment Version=\"3\">\n                <DeployFile LocalName=\"$(BDS)\\Redist\\osx32\\libcgunwind.1.0.dylib\" Class=\"DependencyModule\">\n                    <Platform Name=\"OSX32\">\n                        <Overwrite>true</Overwrite>\n                    </Platform>\n                </DeployFile>\n                <DeployFile LocalName=\"$(BDS)\\Redist\\iossimulator\\libcgunwind.1.0.dylib\" Class=\"DependencyModule\">\n                    <Platform Name=\"iOSSimulator\">\n                        <Overwrite>true</Overwrite>\n                    </Platform>\n                </DeployFile>\n                <DeployFile LocalName=\"$(BDS)\\Redist\\iossimulator\\libpcre.dylib\" Class=\"DependencyModule\">\n                    <Platform Name=\"iOSSimulator\">\n                        <Overwrite>true</Overwrite>\n                    </Platform>\n                </DeployFile>\n                <DeployFile LocalName=\"Win32\\Debug\\Test.exe\" Configuration=\"Debug\" Class=\"ProjectOutput\">\n                    <Platform Name=\"Win32\">\n                        <RemoteName>Test.exe</RemoteName>\n                        <Overwrite>true</Overwrite>\n                    </Platform>\n                </DeployFile>\n                <DeployClass Name=\"AdditionalDebugSymbols\">\n                    <Platform Name=\"OSX32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"Win32\">\n                        <Operation>0</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"AndroidClassesDexFile\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>classes</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"AndroidFileProvider\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\xml</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"AndroidGDBServer\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>library\\lib\\armeabi-v7a</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"AndroidLibnativeArmeabiFile\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>library\\lib\\armeabi</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"AndroidLibnativeMipsFile\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>library\\lib\\mips</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"AndroidServiceOutput\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>library\\lib\\armeabi-v7a</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"AndroidSplashImageDef\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"AndroidSplashStyles\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\values</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"AndroidSplashStylesV21\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\values-v21</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_Colors\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\values</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_DefaultAppIcon\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_LauncherIcon144\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-xxhdpi</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_LauncherIcon36\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-ldpi</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_LauncherIcon48\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-mdpi</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_LauncherIcon72\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-hdpi</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_LauncherIcon96\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-xhdpi</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_NotificationIcon24\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-mdpi</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_NotificationIcon36\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-hdpi</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_NotificationIcon48\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-xhdpi</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_NotificationIcon72\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-xxhdpi</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_NotificationIcon96\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-xxxhdpi</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_SplashImage426\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-small</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_SplashImage470\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-normal</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_SplashImage640\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-large</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_SplashImage960\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\drawable-xlarge</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"Android_Strings\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>res\\values</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"DebugSymbols\">\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"OSX32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"Win32\">\n                        <Operation>0</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"DependencyFramework\">\n                    <Platform Name=\"OSX32\">\n                        <Operation>1</Operation>\n                        <Extensions>.framework</Extensions>\n                    </Platform>\n                    <Platform Name=\"OSX64\">\n                        <Operation>1</Operation>\n                        <Extensions>.framework</Extensions>\n                    </Platform>\n                    <Platform Name=\"Win32\">\n                        <Operation>0</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"DependencyModule\">\n                    <Platform Name=\"OSX32\">\n                        <Operation>1</Operation>\n                        <Extensions>.dylib</Extensions>\n                    </Platform>\n                    <Platform Name=\"OSX64\">\n                        <Operation>1</Operation>\n                        <Extensions>.dylib</Extensions>\n                    </Platform>\n                    <Platform Name=\"Win32\">\n                        <Operation>0</Operation>\n                        <Extensions>.dll;.bpl</Extensions>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Required=\"true\" Name=\"DependencyPackage\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                        <Extensions>.dylib</Extensions>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                        <Extensions>.dylib</Extensions>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                        <Extensions>.dylib</Extensions>\n                    </Platform>\n                    <Platform Name=\"OSX32\">\n                        <Operation>1</Operation>\n                        <Extensions>.dylib</Extensions>\n                    </Platform>\n                    <Platform Name=\"OSX64\">\n                        <Operation>1</Operation>\n                        <Extensions>.dylib</Extensions>\n                    </Platform>\n                    <Platform Name=\"Win32\">\n                        <Operation>0</Operation>\n                        <Extensions>.bpl</Extensions>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"File\">\n                    <Platform Name=\"Android\">\n                        <Operation>0</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>0</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>0</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>0</Operation>\n                    </Platform>\n                    <Platform Name=\"OSX32\">\n                        <Operation>0</Operation>\n                    </Platform>\n                    <Platform Name=\"OSX64\">\n                        <Operation>0</Operation>\n                    </Platform>\n                    <Platform Name=\"Win32\">\n                        <Operation>0</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPad_Launch1024x768\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPad_Launch1536x2048\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPad_Launch1668\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPad_Launch1668x2388\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPad_Launch2048x1536\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPad_Launch2048x2732\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPad_Launch2224\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPad_Launch2388x1668\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPad_Launch2732x2048\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPad_Launch768x1024\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch1125\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch1136x640\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch1242\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch1242x2688\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch1334\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch1792\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch2208\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch2436\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch2688x1242\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch320\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch640\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch640x1136\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch750\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"iPhone_Launch828\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"ProjectAndroidManifest\">\n                    <Platform Name=\"Android\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"ProjectiOSDeviceDebug\">\n                    <Platform Name=\"iOSDevice32\">\n                        <RemoteDir>..\\$(PROJECTNAME).app.dSYM\\Contents\\Resources\\DWARF</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <RemoteDir>..\\$(PROJECTNAME).app.dSYM\\Contents\\Resources\\DWARF</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"ProjectiOSDeviceResourceRules\"/>\n                <DeployClass Name=\"ProjectiOSEntitlements\"/>\n                <DeployClass Name=\"ProjectiOSInfoPList\"/>\n                <DeployClass Name=\"ProjectiOSResource\">\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"ProjectOSXDebug\"/>\n                <DeployClass Name=\"ProjectOSXEntitlements\"/>\n                <DeployClass Name=\"ProjectOSXInfoPList\"/>\n                <DeployClass Name=\"ProjectOSXResource\">\n                    <Platform Name=\"OSX32\">\n                        <RemoteDir>Contents\\Resources</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"OSX64\">\n                        <RemoteDir>Contents\\Resources</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Required=\"true\" Name=\"ProjectOutput\">\n                    <Platform Name=\"Android\">\n                        <RemoteDir>library\\lib\\armeabi-v7a</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSDevice64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"iOSSimulator\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"Linux64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"OSX32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"OSX64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"Win32\">\n                        <Operation>0</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"ProjectUWPManifest\">\n                    <Platform Name=\"Win32\">\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"Win64\">\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"UWP_DelphiLogo150\">\n                    <Platform Name=\"Win32\">\n                        <RemoteDir>Assets</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"Win64\">\n                        <RemoteDir>Assets</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <DeployClass Name=\"UWP_DelphiLogo44\">\n                    <Platform Name=\"Win32\">\n                        <RemoteDir>Assets</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                    <Platform Name=\"Win64\">\n                        <RemoteDir>Assets</RemoteDir>\n                        <Operation>1</Operation>\n                    </Platform>\n                </DeployClass>\n                <ProjectRoot Platform=\"iOSDevice64\" Name=\"$(PROJECTNAME).app\"/>\n                <ProjectRoot Platform=\"Win64\" Name=\"$(PROJECTNAME)\"/>\n                <ProjectRoot Platform=\"iOSDevice32\" Name=\"$(PROJECTNAME).app\"/>\n                <ProjectRoot Platform=\"Linux64\" Name=\"$(PROJECTNAME)\"/>\n                <ProjectRoot Platform=\"Win32\" Name=\"$(PROJECTNAME)\"/>\n                <ProjectRoot Platform=\"OSX32\" Name=\"$(PROJECTNAME)\"/>\n                <ProjectRoot Platform=\"Android\" Name=\"$(PROJECTNAME)\"/>\n                <ProjectRoot Platform=\"OSX64\" Name=\"$(PROJECTNAME)\"/>\n                <ProjectRoot Platform=\"iOSSimulator\" Name=\"$(PROJECTNAME).app\"/>\n            </Deployment>\n            <Platforms>\n                <Platform value=\"Android\">False</Platform>\n                <Platform value=\"Win32\">True</Platform>\n                <Platform value=\"Win64\">True</Platform>\n            </Platforms>\n        </BorlandProject>\n        <ProjectFileVersion>12</ProjectFileVersion>\n    </ProjectExtensions>\n    <Import Project=\"$(BDS)\\Bin\\CodeGear.Delphi.Targets\" Condition=\"Exists('$(BDS)\\Bin\\CodeGear.Delphi.Targets')\"/>\n    <Import Project=\"$(APPDATA)\\Embarcadero\\$(BDSAPPDATABASEDIR)\\$(PRODUCTVERSION)\\UserTools.proj\" Condition=\"Exists('$(APPDATA)\\Embarcadero\\$(BDSAPPDATABASEDIR)\\$(PRODUCTVERSION)\\UserTools.proj')\"/>\n    <Import Project=\"$(MSBuildProjectName).deployproj\" Condition=\"Exists('$(MSBuildProjectName).deployproj')\"/>\n</Project>\n"
  },
  {
    "path": "Test/uTest.pas",
    "content": "unit uTest;\n\ninterface\n\nuses\n  DUnitX.TestFramework, DDetours;\n\ntype\n\n  [TestFixture]\n  TDDetours = class(TObject)\n  public\n    [Setup]\n    procedure Setup;\n    [TearDown]\n    procedure TearDown;\n    // Sample Methods\n    // Simple single Test\n    [Test]\n    procedure Test1;\n    [Test]\n    procedure Test2;\n    [Test]\n    procedure Test3;\n    [Test]\n    procedure Test4;\n  end;\n\nimplementation\n\nconst\n  Pi = 3.14;\n\nconst\n  NewPi = 3.14159265359;\n\ntype\n  TAdd = function(a, b: Integer): Integer;\n  TSub = function(a, b: Integer): Integer;\n  TGetPi = function(): Extended;\n\nvar\n  TrampolineAdd: TAdd = nil;\n  TrampolineSub: TSub = nil;\n  TrampolineGetPi: TGetPi = nil;\n\n  FInterceptSub: TIntercept<TSub, Integer>;\n\nfunction Add(a, b: Integer): Integer;\nbegin\n  Result := a + b;\nend;\n\nfunction Sub(a, b: Integer): Integer;\nbegin\n  Result := a - b;\nend;\n\nfunction GetPi(): Extended;\nbegin\n  Result := Pi;\nend;\n\nfunction InterceptAdd(a, b: Integer): Integer;\nbegin\n  Result := TrampolineAdd(a, b);\nend;\n\nfunction InterceptSub(a, b: Integer): Integer;\nvar\n  Param: Integer;\nbegin\n  Param := Integer(GetTrampolineParam(TrampolineSub));\n  Result := TrampolineSub(a, Param);\nend;\n\nfunction InterceptSub2(a, b: Integer): Integer;\nbegin\n  Result := FInterceptSub.TrampoLine(a, FInterceptSub.Param);\nend;\n\nfunction InterceptGetPi(): Extended;\nbegin\n  Result := NewPi;\nend;\n\nprocedure TDDetours.Setup;\nbegin\n\nend;\n\nprocedure TDDetours.TearDown;\nbegin\nend;\n\nprocedure TDDetours.Test1;\nvar\n  a, b, c: Integer;\nbegin\n  a := 3;\n  b := 2;\n  c := a + b;\n  TrampolineAdd := InterceptCreate(@Add, @InterceptAdd);\n  Assert.AreEqual(Add(a, b), c);\n  InterceptRemove(@TrampolineAdd);\n  Assert.AreEqual(Add(a, b), c);\nend;\n\nprocedure TDDetours.Test2;\nvar\n  a, b, c: Integer;\n  Param: Pointer;\nbegin\n  a := 3;\n  b := 2;\n  c := a - b;\n  Param := Pointer(0);\n  TrampolineSub := InterceptCreate(@Sub, @InterceptSub, Param, DefaultInterceptOptions);\n  Assert.AreEqual(Sub(a, b), a);\n  InterceptRemove(@TrampolineSub);\n  Assert.AreEqual(Sub(a, b), c);\nend;\n\nprocedure TDDetours.Test3;\nbegin\n  TrampolineAdd := InterceptCreate(@GetPi, @InterceptGetPi);\n  Assert.AreEqual(GetPi(), NewPi);\n  InterceptRemove(@TrampolineAdd);\n  Assert.AreEqual(GetPi(), Pi);\nend;\n\nprocedure TDDetours.Test4;\nvar\n  a, b, c: Integer;\nbegin\n  a := 3;\n  b := 2;\n  c := a - b;\n  FInterceptSub := TIntercept<TSub, Integer>.Create(Sub, InterceptSub2, 0);\n  Assert.AreEqual(Sub(a, b), a);\n  FInterceptSub.Free();\n  Assert.AreEqual(Sub(a, b), c);\nend;\n\ninitialization\n\nTDUnitX.RegisterTestFixture(TDDetours);\n\nend.\n"
  }
]