Introducción
En el sistema operativo Windows, un gancho es
un mecanísmo en el cual una función puede interceptar eventos
(mensajes, acciones del ratón, pulsaciones en el teclado) antes de llegar
a su destino. La función puede actuar en eventos, y en algunos casos,
modificarlos o deshacerse de ellos. Las funciones que reciben los eventos son
llamadas Funciones filtro y están clasificadas de acuerdo al
tipo de evento que interceptan.
Por ejemplo una función filtro podría querer recibir todos los
eventos del teclado y del ratón. Para que Windows pueda llamar una función
filtro, la función filtro debe estar instalada primero (por ejemplo,
a un gancho de teclado). Si un gancho tiene mas de una función filtro
instalada, Windows mantiene una cadena de funciones filtro. La última
función filtro instalada estará al principio de la cadena, y la
primera estará al final de la cadena.
Para mantener y accesar a las
funciones filtro, los programas usan las funciones SetWindowsHookEx y
UnhookWindowsHookEx.
Ganchos proveen capacidades
poderosas a los programas que usan el sistema operativo Windows. Estos programas
pueden usar ganchos para:
-
Procesar o modificar todos los
mensajes que tienen como destino, dialog boxes, message boxes, scroll bars, o
menus, para un programa (WH_MSGFILTER).
-
Procesar o modificar todos los
mensajes que tienen como destino, dialog boxes, message boxes, scroll bars, or
menus, para el sistema (WH_SYSMSGFILTER).
- Procesar o modificar todos los mensajes (de
cualquier tipo) para el sistema siempre que la función GetMessage
o PeekMessage sea llamada (WH_GETMESSAGE).
-
Procesar o modificar todos los
mensajes (de cualquier tipo) siempre que la funcion SendMessage sea
llamada (WH_CALLWNDPROC).
- Grabar o repetir (play back) eventos del
teclado y ratón (WH_JOURNALRECORD, WH_JOURNALPLAYBACK).
- Procesar, modificar o remover eventos del
teclado (WH_KEYBOARD).
- Procesar, modificar o deshacer eventos del
ratón (WH_MOUSE).
-
Responder a ciertas acciones del
sistema (WH_CBT).
-
Prevenir otra funcion filtro de
ser llamada (WH_DEBUG)
Como usar los ganchos
Para usar los ganchos, necesitas saber:
- Como usar las funciones de ganchos de
Windows para instalar y desinstalar las funciones filtro de la cadena de
funciones filtros del gancho.
- Qué acción la función
filtro que estás instalando realizará.
- Qué tipos de ganchos estan disponibles,
qué pueden hacer, y qué información (parámetros)
pasarán a tu función filtro.
Funciones de gancho en Windows
Programas basados en Windows usan las funciones
SetWindowsHookEx, UnhookWindowsHookEx, y CallNextHookEx
para manejar los ganchos en la cadena de funciones filtro. Antes de la version
3.1, Windows manejaba los ganchos con las funciones SetWindowsHook,
UnhookWindowsHook, y DefHookProc. Aunque estas funciones estan implementadas
en la Win32, tienen menos capacidades que la version nueva (Ex). Así
que debes usar las versiones nuevas de estas funciones.
SetWindowsHookEx
La funcion SetWindowsHookEx agrega una
función filtro al gancho. Esta función necesita cuatro argumentos
(parámetros):
- Un entero (integer) describiendo el tipo de
gancho.
- La dirección de la función filtro
(puntero de la función filtro)
- El manejador (handle) de la instancia del
modulo que contiene la función filtro. En la Win32, este valor debe
ser NULL cuando se instala un gancho a un hilo (thread) específico,
pero no tiene que ser NULL como dice la documentación. Cuando instalas
un gancho a todo el sistema (systemwide) o un gancho a un hilo específico
en otro proceso, debes de usar el manejador de la instancia de la DLL donde
la función filtro reside.
- El ID del hilo donde el gancho será
instalado. Si el ID del hilo no es cero, la función filtro instalada
será llamada solo en el contexto del hilo especificado. Si el ID del
hilo es cero, la función filtro instalada tiene alcance de sistema
(global) y puede ser llamada en el contexto de cualquier hilo en el sistema.
Un programa o libreria puede usar la funcion GetCurrentThreadId
para obtener el ID del hilo para instalar un gancho en el hilo actual.
Algunos ganchos pueden ser instalados
solo con alcance de sistema; algunos pueden ser instalados solo a un hilo
especifico; y otros pueden tener cualquier alcance (sistema o hilo especifico),
como muestra la siguiente tabla.
| Hook |
Alcance |
| WH_CALLWNDPROC |
Hilo o Sistema |
| WH_CBT |
Hilo o Sistema |
| WH_DEBUG |
Hilo o Sistema |
| WH_GETMESSAGE |
Hilo o Sistema |
| WH_JOURNALRECORD |
Solo Sistema |
| WH_JOURNALPLAYBACK |
Solo Sistema |
| WH_FOREGROUNDIDLE |
Hilo o Sistema |
| WH_SHELL |
Hilo o Sistema |
| WH_KEYBOARD |
Hilo o Sistema |
| WH_MOUSE |
Hilo o Sistema |
| WH_MSGFILTER |
Hilo o Sistema |
| WH_SYSMSGFILTER |
Solo Sistema |
Ganchos a un hilo son llamados primeros,
seguidos por ganchos al sistema.
Una buena idea es usar ganchos a un hilo en lugar de ganchos al sistema por
varias razones. Ganchos a un hilo:
- El sistema no procesará más
datos ya que muchos programas no estan interesados en la llamada.
- No causa que todos los eventos de un gancho
sea serializado. Por ejemplo, si un programa instala un gancho al teclado
con alcance a todo el sistema, todos los mensajes del teclado de todos los
programas irán a la función filtro de ese programa, efectivamente
gastando la funcionalidad de la multiple cola de entrada del sistema. Si esa
funcion filtro deja de procesar los eventos del teclado, parecerá que
el sistema se ha parado, pero no estara parado realmente. El usuario puede
usar siempre la combinacion CTRL+ALT+DELETE para hacer log out, y resolver
el problema, pero no estará probablemente feliz con todo eso.
- No requiere que la implementacion de una funcion
filtro esté en una DLL. Todos los ganchos de alcance al sistema y ganchos
a un hilo que no sea al tuyo (hilo de otro programa) deben estar en una DLL.
- No se necesita compartir data dentro de una
DLL en diferentes procesos. Una función filtro de alcance al sistema
que reside dentro de una DLL, debe también compartir cualquier data
que necesite en otros procesos. Ya que esta no es el comportamiento de
una DLL, tienes que tener cuidado cuando implementes funciones filtro de alcance
al sistema. Si la función filtro no comparte data correctamente y usa
la data en otro proceso donde es inválido, entonces el proceso puede
hacer crash.
SetWindowsHookEx
retorna un manejador al gancho instalado (un HHOOK). El programa o librería
debe usar este manejador para identificar a este gancho luego cuando se llame
a la funcion UnhookWindowsHookEx. SetWindowsHookEx retorna NULL
si es que no puede instalar el gancho. SetWindowsHookEx tambien nos
avisa por medio del último error (last error), por qué la función
falló.
- ERROR_INVALID_HOOK_FILTER: El codigo del gancho
es inválido.
- ERROR_INVALID_FILTER_PROC: La funcion filtro
es inválida.
- ERROR_HOOK_NEEDS_HMOD: Un gancho global (alcance
de sistema) esta siendo instalado con una instancia NULL, o un gancho a un
hilo especifico está siendo instalado a un hilo que no corresponde
a la de tu programa.
- ERROR_GLOBAL_ONLY_HOOK: Un gancho que solo
puede ser global, está siendo instalado a un hilo específico.
- ERROR_INVALID_PARAMETER: El ID del hilo es
inválido.
- ERROR_JOURNAL_HOOK_SET: Ya existe un gancho
instalado, para un gancho de tipo journal. Solo un gancho de tipo journal
o journal playback puede ser instalado a la vez. Este error también
puede suceder si tu programa trata de instalar un gancho de tipo journal,
mientras que un screen saver está activo.
- ERROR_MOD_NOT_FOUND: La instancia para un
gancho global no es la de una DLL.
- Otros valores: La seguridad no permite
instalar el gancho, o el sistema se quedo sin memoria.
UnhookWindowsHookEx
Para remover una función filtro de la
cadena de ganchos, llama a la funcion UnhookWindowsHookEx. Esta función
toma el manejador del gancho retornado por SetWindowsHookEx y retorna
un valor indicando si el gancho fue removido. UnhookWindowsHookEx siempre
retorna TRUE.
Funciones filtro
Las funciones filtros son llamadas por Windows
y no por programas, estas funciones son algunas veces referidas como funciones
callback. Todas las funciones filtro deben tener la forma de abajo, y
deben retornar un long. Los parámetros que recibe la función filtro
depende del tipo de gancho. CallNextHookEx necesita cuatro parámetros,
el primero, es lo que retorna SetWindowsHookEx, y tres siguientes son
los parámetros nCode, wParam, y lParam de la función filtro.
function FilterProc(nCode:
Integer; wParam:
WPARAM; lParam: LPARAM):
LRESULT; stdcall;
begin
(* tu codigo *)
end;
Mas Informacion