Document of interface ICodeHook

This is the root and kernel interface of Win32 CodeHook.
You can call GetCodeHook to get the root interface.
You can also call ICodeHook.CreateCodeHook to create a new interface.
It supports both raw mode hook and advanced hook.

Delphi syntax:
ICodeHook = interface(IErrorCodeHook)
	procedure GetDirectCodeHook(out Obj); stdcall;
	procedure GetCodeHookHelper(out Obj); stdcall;
	procedure CreateCodeHook(out Obj); stdcall;
	procedure SetUserDataSize(ASize: Integer); stdcall;
	function Hook(ATarget, AHook: Pointer): TCodeHookHandle; stdcall;
	function Unhook(AHandle: TCodeHookHandle): LongBool; stdcall;
	function GetHookInfo(AHandle: TCodeHookHandle; AInfo: PCodeHookInfo): LongBool; stdcall;
	function GetUserData(AHandle: TCodeHookHandle): Pointer; stdcall;
	function AdvancedHook(ATargetObject: Pointer;
		ATarget: Pointer; ATargetCallingConvention: Integer;
		AHook: Pointer; AHookCallingConvention: Integer;
		AParamCount: Integer;
		AExtraParams: PCardinal; AExtraParamCount: Integer;
		AFlags: Cardinal): TCodeHookHandle; stdcall;
	function AdvancedUnhook(AHandle: TCodeHookHandle): LongBool; stdcall;
	function FindHookHandleFromTarget(ATarget: Pointer): TCodeHookHandle; stdcall;
	function CallPreviousMethod(AHandle: TCodeHookHandle; AParams: PCardinal): Cardinal; stdcall;
	function CallMethod(AObject: Pointer; AMethod: Pointer;
		AParams: PCardinal; AParamCount: Integer; ACallingConvention: Integer): Cardinal; stdcall;
end;
C++ syntax:
class ICodeHook: public ICodeHookError {
public:
	virtual void _stdcall GetDirectCodeHook(IDirectCodeHook **) = 0;
	virtual void _stdcall GetCodeHookHelper(ICodeHookHelper **) = 0;
	virtual void _stdcall CreateCodeHook(ICodeHook **) = 0;
	virtual void _stdcall SetUserDataSize(int Size) = 0;
	virtual TCodeHookHandle _stdcall Hook(Pointer Target, Pointer Hook) = 0;
	virtual BOOL _stdcall Unhook(TCodeHookHandle Handle) = 0;
	virtual BOOL _stdcall GetHookInfo(TCodeHookHandle Handle, PCodeHookInfo Info) = 0;
	virtual Pointer _stdcall GetUserData(TCodeHookHandle Handle) = 0;
	virtual TCodeHookHandle _stdcall AdvancedHook(Pointer TargetObject,
		Pointer Target, int TargetCallingConvention,
		Pointer Hook, int HookCallingConvention,
		int ParamCount,
		PUINT ExtraParams, int ExtraParamCount,
		UINT Flags) = 0;
	virtual BOOL _stdcall AdvancedUnhook(TCodeHookHandle Handle) = 0;
	virtual TCodeHookHandle _stdcall FindHookHandleFromTarget(Pointer Target) = 0;
	virtual UINT _stdcall CallPreviousMethod(TCodeHookHandle Handle, PUINT Params) = 0;
	virtual UINT _stdcall CallMethod(Pointer Object, Pointer Method,
		PUINT Params, int ParamCount, int CallingConvention) = 0;
};
Function:

GetDirectCodeHook


Retrieve interface IDirectCodeHook
Delphi syntax:
procedure GetDirectCodeHook(out Obj); stdcall;

C++ syntax:
virtual void calltype GetDirectCodeHook(IDirectCodeHook **) = 0;


Params
Obj
Address of pointer variable that receives the interface pointer.
Return value
This function doesn't return value.
Function:

GetCodeHookHelper


Retrieve interface ICodeHookHelper
Delphi syntax:
procedure GetCodeHookHelper(out Obj); stdcall;

C++ syntax:
virtual void calltype GetCodeHookHelper(ICodeHookHelper **) = 0;


Params
Obj
Address of pointer variable that receives the interface pointer.
Return value
This function doesn't return value.
Function:

CreateCodeHook


Create an instance of interface ICodeHook
Delphi syntax:
procedure CreateCodeHook(out Obj); stdcall;

C++ syntax:
virtual void calltype CreateCodeHook(ICodeHook **) = 0;


Params
Obj
Address of pointer variable that receives the interface pointer.
Return value
This function doesn't return value.
Remarks
Usually you don't need to call this function because the interface returned by GetCodeHook is enough to you.
Function:

SetUserDataSize


Set the user data record size.
Delphi syntax:
procedure SetUserDataSize(ASize: Integer); stdcall;

C++ syntax:
virtual void calltype SetUserDataSize(int Size) = 0;


Params
ASize
The size of user data in byte.
Return value
This function doesn't return value.
Remarks
You can specify a user data size and call GetUserData to retrieve the user data pointer then you can store information to the user data.
Function:

Hook


Low level hook a method.
Delphi syntax:
function Hook(ATarget, AHook: Pointer): TCodeHookHandle; stdcall;

C++ syntax:
virtual TCodeHookHandle calltype Hook(Pointer Target, Pointer Hook) = 0;


Params
ATarget
Address of the target function.
AHook
Address of the hook function.
Return value
A handle that represents the code hook information.
Remarks
The prototype of the hook function should be exactly same as the target.
That's to say, the parameters count and the calling convention should be same.
Function:

Unhook


Low level unhook a method.
Delphi syntax:
function Unhook(AHandle: TCodeHookHandle): LongBool; stdcall;

C++ syntax:
virtual BOOL calltype Unhook(TCodeHookHandle Handle) = 0;


Params
AHandle
The handle returned by HookMethod.
Return value
Return TRUE on success, otherwise, return FALSE.
Function:

GetHookInfo


Retrieve the hook information.
Delphi syntax:
function GetHookInfo(AHandle: TCodeHookHandle; AInfo: PCodeHookInfo): LongBool; stdcall;

C++ syntax:
virtual BOOL calltype GetHookInfo(TCodeHookHandle Handle, PCodeHookInfo Info) = 0;


Params
AHandle
The handle represents the code hook information
AInfo
Pointer to a TCodeHookInfo record (structure).
Return value
Return TRUE on success, otherwise, return FALSE.
Function:

GetUserData


Retrieve the user data buffer.
Delphi syntax:
function GetUserData(AHandle: TCodeHookHandle): Pointer; stdcall;

C++ syntax:
virtual Pointer calltype GetUserData(TCodeHookHandle Handle) = 0;


Params
AHandle
The handle represents the code hook information
Return value
If the function successes, returns the pointer to the user data.
If the function fails, returns NULL (nil).
Remarks
User data is another way to store customized information beside extra parameters.
User data allow you to store and retrieve any data in the code hook handle.
The initial user data memory is guaranteed to be zero.

Note:
Don't forget to call ICodeHook.SetUserDataSize to set the property user data size, otherwise, you will get wrong user data memory.
Function:

AdvancedHook


Advanced mode hook a method.
Delphi syntax:
function AdvancedHook(ATargetObject: Pointer;
      ATarget: Pointer; ATargetCallingConvention: Integer;
      AHook: Pointer; AHookCallingConvention: Integer;
      AParamCount: Integer;
      AExtraParams: PCardinal; AExtraParamCount: Integer;
      AFlags: Cardinal): TCodeHookHandle; stdcall;

C++ syntax:
virtual TCodeHookHandle calltype AdvancedHook(Pointer TargetObject,
		Pointer Target, int TargetCallingConvention,
		Pointer Hook, int HookCallingConvention,
		int ParamCount,
		PUINT ExtraParams, int ExtraParamCount,
		UINT Flags) = 0;


Params
ATargetObject
Address of the "this" pointer of the target.
If the target is a global function, set this parameter to NULL.
ATarget
Address of the target function.
ATargetCallingConvention
The calling convention of the target function.
AHook
Address of the hook function. See remarks.
AHookCallingConvention
The calling convention of the hook function.
AParamCount
The param count of the target function. See remarks.
AExtraParams
Pointer to extra parameters. See remarks.
AExtraParamCount
The count of extra parameters.
AFlags
For future use. Now pass it with 0.
Return value
A handle that represents the code hook information.
Remarks
Note on the hook function:
The prototype of the hook function should be in a fixed form, independent on the target.
The prototype should be,
Delphi syntax: function HookCallback(AExtraParam1: Cardinal; AExtraParam2: Cardinal .. AExtraParamN: Cardinal; AHandle: TCodeHookHandle; AParams: PCodeHookParamAccessor): Cardinal; CallingConvertion;
C++ syntax: DWORD CallingConvertion HookCallback(DWORD AExtraParam1, DWORD AExtraParam2 .. DWORD AExtraParamN, TCodeHookHandle AHandle, PDWORD AParams);
If no extra parameters, the prototype should be
Delphi syntax: function HookCallback(AHandle: TCodeHookHandle; AParams: PCodeHookParamAccessor): Cardinal; CallingConvertion;
C++ syntax: DWORD CallingConvertion HookCallback(TCodeHookHandle AHandle, PDWORD AParams);

You can access the hook information using AHandle by calling ICodeHook.GetHookInfo.
You can also access the customized user data information using AHandle by calling ICodeHook.GetUserData.

The parameter AParams is the parameters that are passed to the target function. You can access the parameters by accessing AParams[0], AParams[1], etc. For example, if the hook is for Windows API MessageBox, then AParams[0] is the first parameter of MessageBox, hWnd. AParams[1] is the second, lpText, AParams[2] is lpCaption, and AParams[3] is uType.

This function assumes the hook function is a global function. If object function is used as hook, you should better use ICodeHookHelper.HookWithObjectMethod to make the hook.

Note on the parameter count:
AParamCount is base on the presupposition that the target function takes simple parameters.
"Simple" means all parameters are simple data type with no more than 32 bits. The simple data types include byte, char, short, word, int, dword, pointer, single float, etc.
Other types such as double float (64 bits float), Intel extended float (80 bits float), Windows Variant type, record (structure) are not simple.

If non-simple parameters are in the target function, you should better use raw mode hook and make the hook function exactly same prototype with the target function rather than using the advanced hook.

Note on the extra parameters:
You can pass predefined values as extra parameters and fetch the values in the hook function. This is a good place to connect the hook function with current running enviroment. You can pass the necessary information to the hook function as parameters instead of putting it in the global context. A typical very useful use is to pass the "this" pointer if the hook is a class member function.
The extra parameters are passed as partial of the hook function's parameters, beside the code hook handle (AHandle) and the parameter pointer (AParams).

The order passing the mixed parameters is that the first extra parameter is passed, then the second, then the third, after all extra parameters are passed, the code hook handle (AHandle) is passed, and the parameter pointer (AParams) is passed last.
So in both Delphi and C++, when declaring the hook function, the first extra parameter should be at the most left, and the parameter pointer (AParams) should be at the most right.
Function:

AdvancedUnhook


Advanced mode unhook a method.
Delphi syntax:
function AdvancedUnhook(AHandle: TCodeHookHandle): LongBool; stdcall;

C++ syntax:
virtual BOOL calltype AdvancedUnhook(TCodeHookHandle Handle) = 0;


Params
AHandle
The handle returned by AdvancedHook.
Return value
Return TRUE on success, otherwise, return FALSE.
Function:

FindHookHandleFromTarget


Find handle from a given target address.
Delphi syntax:
function FindHookHandleFromTarget(ATarget: Pointer): TCodeHookHandle; stdcall;

C++ syntax:
virtual TCodeHookHandle calltype FindHookHandleFromTarget(Pointer Target) = 0;


Params
ATarget
The target address to find.
Return value
If this function successes, return the handle found. Otherwise, return INVALID_CODEHOOK_HANDLE.
Remarks
To get the target address from a handle, use ICodeHook.GetHookInfo.
Function:

CallPreviousMethod


Call previous function.
Delphi syntax:
function CallPreviousMethod(AHandle: TCodeHookHandle; AParams: PCardinal): Cardinal; stdcall;

C++ syntax:
virtual UINT calltype CallPreviousMethod(TCodeHookHandle Handle, PUINT Params) = 0;


Params
AHandle
The handle that represents the code hook information.
AParams
The pointer to the parameters.
Return value
Return what the previous function returns. If the previous function doesn't return a value, the return value is undefined.
Function:

CallMethod


Call a function with specified calling convention and parameters.
Delphi syntax:
function CallMethod(AObject: Pointer; AMethod: Pointer;
      AParams: PCardinal; AParamCount: Integer; ACallingConvention: Integer): Cardinal; stdcall;

C++ syntax:
virtual UINT calltype CallMethod(Pointer Object, Pointer Method,
		PUINT Params, int ParamCount, int CallingConvention) = 0;


Params
AObject
The object instance if the destination is an object method. If the destination is a global method, set this parameter to NULL.
AMethod
The address of the destination method.
AParams
The pointer to the parameters.
AParamCount
The parameters count.
ACallingConvention
The calling convention of the previous function.
Return value
Return what the function returns. If the function doesn't return a value, the return value is undefined.
Remarks
Usually use CallPreviousMethod instead of this function.
This function should only be used when you use raw mode hooking while you want to call the previous function without prototype.