InstallDllImportHook - Hook calls between modules

Top  Previous  Next

Syntax

 

<aHookInfo> := InstallDllImportHook( <cCallingModule>, <cCalledFunctionName>, <cCalledModule>, <nCallback> )

 

Parameters

 

<cCallingModule>

 

Name of module from which calls to <cCalledFunctionName> are to be hooked.

 

<cCalledFunctionName>

 

Name of function to which calls from <cCallingModule> are to be hooked.

 

<cCalledModule>

 

Name of module to which calls are to be hooked.

 

<cCallback>

 

Address of callback (returned for example by Callback) function to be called instead of the original function.

 

Return value

 

When the operation succeeds an Array of two numeric elements (LONG values) is returned. The first element is the memory address of the original call address in the import table of <cCallingModule> that was modified. The constant to access it is DLLHOOKINFO_INDEX_HOOKADDRESS. The second element is the original call address found in the import table. The constant to access it is DLLHOOKINFO_INDEX_ORIGINALPROCADDRESS. These values can later be used to restore the original call with RemoveDllImportHook.

 

If the operation fails, NIL is returned.

 

Description

 

InstallDllImportHook hooks calls between modules. When a module is loaded, its calls to functions in other modules must be "resolved". Normally the load address of a called module is not known at link time, hence the final addresses of called functions in it cannot be placed in the calling module at link time. This resolution takes place when a module is loaded. Every module comes with an import table containing references to all used functions in other modules. After loading a module (and the ones which it needs that have not been loaded before) the loader fixes its import table: All memory addresses of the used functions are written to its import table. This import table is changed by InstallDllImportHook.

 

The installed callback must receive the passed parameters and use the correct calling convention. If the call is not handled by the callback, it must pass on to the original function. This can be accomplished with CallAddress using the second element of <aHookInfo> as address to be called. Don't forget to pass on the received parameters in this case.

 

Classification

 

Core

 

Category

 

Hook

 

Quick Info

 

Library: cckptcor.lib /cckptcor.dll

Header: DllImportHook.ch

 

See also

 

RemoveDllImportHook

 

Example

 

 

#INCLUDE "CockpitPlatformLibs.ch"

#INCLUDE "Windows.ch"

#INCLUDE "DllImportHook.ch"

 

STATIC originalAddress

 

FUNCTION main

 

LOCAL hookInfo,envValue

 

* Hook any call from "xpprt1.dll" to "GetEnvironmentVariableA" in dll "kernel32.dll"

* to the callback function "MyHookFunc"

hookInfo := InstallDllImportHook("xpprt1.dll","GetEnvironmentVariableA",;

                                "kernel32.dll",MyHookFunc())

 

* That didn't work?

IF hookInfo == NIL

  MessageBox(0,"Hooking failed")

  CANCEL

ENDIF

 

* Save the original address for passsing on the call to the original function

originalAddress := hookInfo[DLLHOOKINFO_INDEX_ORIGINALPROCADDRESS]

 

MessageBox(0,"Hooking successful.")

 

* HOOKINFO is our special value

envValue := GETENV("HOOKINFO")

 

* Display what we received

MessageBox(0,SVI("Returned value for HOOKINFO: &1",envValue))

 

* Any other value should return the real value of the environment variable

envValue := GETENV("SystemRoot")

 

* Display what we received

MessageBox(0,SVI("Returned value for SystemRoot: &1",envValue))

 

* Now remove the Hook

RemoveDllImportHook(hookInfo)

MessageBox(0,"Hook removed.")

 

* Now let's see what GETENV returns

envValue := GETENV("HOOKINFO")

 

* Display what we received (should be empty this time but it isn't, hence

* Xbase++ caches environment variables!)

MessageBox(0,SVI("Returned value for HOOKINFO after unhooking: &1",envValue))

 

RETURN NIL

 

 

 

* This function is called instead of the original GetEnvironmentVariableA function

CALLBACK FUNCTION MyHookFunc(p1,p2,p3)

 

* Display the passed parameters

MessageBox(0,SVI("GetEnvironmentVariableA(&1,&2,&3)",CopyMemoryToString(p1),p2,p3),;

          "Hook function called")

 

* Handle our special case...

IF CopyMemoryToString(p1) == "HOOKINFO"

 

  * Size Request?

  IF p3 == 0

     RETURN 11

  ENDIF

 

  * Return our special result value

  WriteMemory(p2,"Holy Moly!"+CHR(0),11)

 

  * Return the size

  RETURN 10

 

ENDIF

 

* Pass the call on to the original function

RETURN CallAddress(originalAddress,p1,p2,p3)