dim shared as any ptr MYESP,MYEAX,MYEBP
dim shared as any ptr RESP,REBP,REAX,REBX
dim shared as any ptr ORGRET,DDRAWRET
dim shared as any ptr FUNCRESULT

'#include once "detour.bi"
'#include once "..\Includes\x86dis.bi"
#include once "MyTDT\Detour.bas"
#include once "Detoured.bas"
#include once "crt.bi"

#if 0
#macro FunctionDetour(FUNCNAME)
  ORGFUNC = GetProcAddress(DLLHAN,#FUNCNAME)
  if ORGFUNC then
    asm mov dword ptr [TRAMPFUNC],offset FUNCNAME##Trampoline
    RESU = CreateDetour2(ORGFUNC,@FUNCNAME##Z, TRAMPFUNC)      
    printf("Detour Created to "+#FUNCNAME+" (" & RESU & !")\n" )    
    #ifdef CtlDebugDetourCreation
    ccout("Detour Created to "+#FUNCNAME+" (" & RESU & ")" )    
    #endif
  else  
    printf("Failed to Create "+#FUNCNAME+!" detour...\n")
    #ifdef CtlDebugDetourCreation  
    ccout("Failed to Create "+#FUNCNAME+" detour...")    
    #endif
  end if
#endmacro

' ******************************************************************************************
' ***************************** Function that create API detour ****************************
' ******************************************************************************************
function CreateDetour2(ORGPTR as any ptr,DETOURPTR as any ptr=0,TRAMPOLINEPTR as any ptr=0) as integer
  
  dim as integer PROTA,PROTB,RESU
  dim as integer PRESU,PSKIP
  dim as any ptr PDETOUR = ORGPTR
  
  if VirtualProtect(ORGPTR,16,PAGE_EXECUTE_READWRITE,@PROTB) = 0 then return 0  
  if TRAMPOLINEPTR then
    if VirtualProtect(TRAMPOLINEPTR,16,PAGE_EXECUTE_READWRITE,@PROTA) = 0 then return 0    
    ' *** creating trampoline function ***
    PRESU=0:PSKIP=0
    do 'calculating detour size...
      PRESU = LD32(PDETOUR) 'Getting Size of next ASM instruction
      if PRESU = 0 then
        PDETOUR += 1:PSKIP += 1
      else
        PDETOUR += PRESU:PSKIP += PRESU
      end if
    loop while PSKIP < 5 or PRESU = 0    
    if PRESU=0 then return 0
    asm
      mov ESI,[ORGPTR]         ' Original function
      mov EDI,[TRAMPOLINEPTR]  ' Trampoline function
      mov ECX,[PSKIP]          ' instruction bytes (aligned)
      rep movsb                ' Copy original instructions
      mov AL,0xE9              ' jmp
      stosb                    ' store jmp
      mov EAX,[ORGPTR]         ' [ORGPTR]  ' real ptr
      add EAX,[PSKIP]          ' skipped bytes
      sub EAX,EDI              ' convert into offset
      sub EAX,4                ' adjust
      stosd                    ' store offset
    end asm  
    FlushInstructionCache(GetCurrentProcess(),TRAMPOLINEPTR,16) ' / both functions
  else
    DETOURPTR = ORGPTR
  end if
  
  ' *** detouring original function ***
  asm
    mov EDI, [ORGPTR]             ' offset code    
    mov AL,0xE9                   ' jmp
    stosb                         ' store jmp
    mov EAX,[DETOURPTR]           ' [DETOURPTR]           ' real ptr
    sub EAX,EDI                   ' convert into offset
    sub EAX,4                     ' adjust
    stosd                         ' store offset
  end asm
  
  VirtualProtect(TRAMPOLINEPTR,16,PROTA,@RESU)   ' \ restoring original access
  VirtualProtect(ORGPTR,16,PROTB,@RESU)          ' / of both functions
  FlushInstructionCache(GetCurrentProcess(),ORGPTR,16)        ' \ flushing cache
  
  return PSKIP
  
end function
function CreateSimpleDetour(ORGPTRPTR as any ptr ptr,DETOURPTR as any ptr=0,TRAMPOLINEPTR as any ptr=0) as integer
  
  dim as integer PROTA,PROTB,RESU
  dim as integer PRESU,PSKIP
  dim as any ptr PDETOUR = TRAMPOLINEPTR
  dim as any ptr ORGPTR = *ORGPTRPTR
  if *ORGPTRPTR = DETOURPTR then return 0
  *ORGPTRPTR = DETOURPTR
  if TRAMPOLINEPTR then
    if VirtualProtect(TRAMPOLINEPTR,16,PAGE_EXECUTE_READWRITE,@PROTA) = 0 then return 0  
    *cptr(any ptr ptr,TRAMPOLINEPTR-4) = ORGPTR      
    VirtualProtect(TRAMPOLINEPTR,16,PROTA,@RESU)   ' \ restoring original access  
    FlushInstructionCache(GetCurrentProcess(),TRAMPOLINEPTR,16)        ' \ flushing cache
  end if
  
  return -1
  
end function
#endif

' ****************************************************************************************
' ************************ CREATING ALL DETOURS FOR COMMANDOS ****************************
' ****************************************************************************************
sub CreatePreDetours()
  'PMYTABLE2048 = @MYTABLE2048(0)
  'disasm_init(PMYTABLE2048)
  dim as hmodule DLLHAN  
  dim as any ptr ORGFUNC,TRAMPFUNC
  dim as integer RESU  
  SetDetourLibrary("user32")    
  CreateDetour(RegisterClassA)  
  CreateDetour(CreateWindowExA)
end sub
Sub CreateDetours()
  
  dim as hmodule DLLHAN  
  dim as any ptr ORGFUNC,TRAMPFUNC
  dim as integer RESU
  
  'DLLHAN = GetModuleHandle("user32.dll")
  'if DLLHAN=0 then DLLHAN = LoadLibrary("user32.dll")  
  'FunctionDetour(RegisterClassA)
  'FunctionDetour(CreateWindowExA)  
  ' *****************************************************************************    
  DLLHAN = GetModuleHandle("dplayx.dll")
  if DLLHAN=0 then DLLHAN = LoadLibrary("dplayx.dll")
  'FunctionDetour(DirectPlayCreate)
  ''FunctionDetour(DirectPlayEnumerateA)
  ' *****************************************************************************    
  DLLHAN = GetModuleHandle("kernel32.dll")
  if DLLHAN=0 then DLLHAN = LoadLibrary("kernel32.dll")
  ''FunctionDetour(CreateFileA)
  ''FunctionDetour(CloseHandle)
  ''FunctionDetour(WriteFile)
  ' *****************************************************************************  
  DLLHAN = GetModuleHandle("Winmm.dll")
  if DLLHAN=0 then DLLHAN = LoadLibrary("Winmm.dll")  
  ''FunctionDetour(mciSendCommandA)
  ' *****************************************************************************
  DETOURED = 1
  ' ********************************************************************
  
end sub