Posts Tagged ‘hook

13
May
09

[C++] CBT Hook Example

Got bored of doing revision and started on a HookLib, this is an example program where I was testing using a CBT Hook.

header.h

#include "windows.h"

bool SetCBTHook(DWORD, HWND);
void RemoveCBTHook(); 

Main.cpp

#include "header.h"

#define IDC_LIST 4000

HINSTANCE	mhInstance;
HWND		mhWnd;
HWND		lvhWnd;

LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
    {
		case WM_COMMAND:
               break;
		case WM_DESTROY:
			RemoveCBTHook();
			PostQuitMessage (0); 
			break;
		default: 
			return DefWindowProc (hwnd, message, wParam, lParam);
    }
    return 0;
}

BOOL RegisterClass(wchar_t szClassName[])
{
    WNDCLASSEX wc;
    wc.hInstance =  mhInstance;
    wc.lpszClassName = (LPCWSTR)szClassName;
    wc.lpfnWndProc = WindowProc; 
    wc.style = CS_DBLCLKS;
    wc.cbSize = sizeof (WNDCLASSEX);
    wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wc.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor (NULL, IDC_ARROW);
    wc.lpszMenuName = NULL;
    wc.cbClsExtra = 0; 
    wc.cbWndExtra = 0;
    wc.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
    if (!RegisterClassEx (&wc))
		return 0;
	else
		return 1;
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPreviousInstance,LPSTR lpcmdline,int nCmdShow)
{
	MSG messages;
	mhInstance = hInstance;
	wchar_t ClassName[ ] = L"CBTHookClass";
	wchar_t WindowName[ ] = L"CBTHookWindow";
	RegisterClass(ClassName);
	mhWnd = CreateWindowEx(WS_EX_CONTROLPARENT, ClassName, WindowName, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE | WS_MAXIMIZEBOX, 0, 0, 500, 500, NULL, NULL, hInstance, NULL);
	lvhWnd = CreateWindow(L"LISTBOX",L"CBTHookListBox",WS_CHILD|WS_VISIBLE|WS_VSCROLL, 2,2,490,479,mhWnd, (HMENU)IDC_LIST,hInstance, NULL );
	SetCBTHook(GetCurrentThreadId(), mhWnd);
	while (GetMessage (&messages, NULL, 0, 0))
    {
		TranslateMessage(&messages);
        DispatchMessage(&messages);
    }
    return 0;
} 

CBTHook.cpp

#include "header.h"
#include <stdlib.h>
#include <sstream>
#include <string>


HHOOK	CBT_HOOK_ID;
HWND	hWnd;

using namespace std;

std::wstring StringToWString(const std::string& s)
{
	std::wstring temp(s.length(),L' ');
	std::copy(s.begin(), s.end(), temp.begin());
	return temp; 
}

void AddItem(LPCWSTR text) {
	SendDlgItemMessage(hWnd, 4000, LB_ADDSTRING, 0, (LPARAM)text);
}

void AddHWND(WPARAM hwnd) {
	ostringstream oss;
	oss << hex << (int)hwnd;
	wstring Message = L" ---Window Handle: 0x" + StringToWString(oss.str());
	AddItem(Message.c_str());
}

//void AddRECT(RECT rect) {
//	string out;
//	ostringstream oss;
//	oss << rect.top;
//	out = oss.str();
//	oss << rect.bottom;
//	out = out + ", " + oss.str();
//	oss << rect.left;
//	out = out + ", " + oss.str();
//	oss << rect.right;
//	out = out + ", " + oss.str();
//	wstring Message = L"Window Moved/Resized: " + StringToWString(out);
//}

static LRESULT CALLBACK CBTHookProc(int nCode, WPARAM wParam, LPARAM lParam)   
{  
	if(nCode > 0) {
		CBT_CREATEWND	*CBTHOOKCREATE;
		RECT			*CBTRECTPTR;
		RECT			CBTRECT;
		wstring			Message;
		
		switch (nCode)
		{
			case HCBT_ACTIVATE:
				AddItem(L"Window Activated");
			case HCBT_CREATEWND:
				CBTHOOKCREATE = (CBT_CREATEWND*) lParam;
				AddItem(L"Window Created");
				Message = L" ---Window Name: ";
				if(!IsBadReadPtr(CBTHOOKCREATE->lpcs, 1)) {
					if(!IsBadReadPtr(CBTHOOKCREATE->lpcs->lpszName, 1))
						Message = Message + CBTHOOKCREATE->lpcs->lpszName;
				}
				AddItem(Message.c_str());

				Message = L" ---Window Class: ";
				if(!IsBadReadPtr(CBTHOOKCREATE->lpcs, 1)) {
					if(!IsBadReadPtr(CBTHOOKCREATE->lpcs->lpszClass, 1))
						Message = Message + CBTHOOKCREATE->lpcs->lpszClass;
				}
				AddItem(Message.c_str());
				AddHWND(wParam);
			case HCBT_DESTROYWND:
				AddItem(L"Window Destroyed");
			case HCBT_MINMAX:
				switch(lParam)
				{
				case SW_HIDE:
					AddItem(L"Window Hidden");
					break;
				case SW_MAXIMIZE:
					AddItem(L"Window Maximized");
					break;
				case SW_MINIMIZE:
					AddItem(L"Window Minimized");
					break;
				case SW_RESTORE:
					AddItem(L"Window Restored");
					break;
				case SW_SHOW:
					AddItem(L"Window Shown");
					break;
				case SW_SHOWDEFAULT:
					AddItem(L"Window Shown Default");
					break;
				case SW_SHOWMINIMIZED:
					AddItem(L"Window Shown Minimized");
					break;
				case SW_SHOWMINNOACTIVE:
					AddItem(L"Window Shown Minimized (Not Active)");
					break;
				case SW_SHOWNA:
					AddItem(L"Window Shown (Not Active)");
					break;
				case SW_SHOWNOACTIVATE:
					AddItem(L"Window Shown (Not Active)");
					break;
				case SW_SHOWNORMAL:
					AddItem(L"Window Shown");
					break;
				}
				AddHWND(wParam);
			case HCBT_MOVESIZE:
				//CBTRECTPTR = (RECT*) lParam;
				//memcpy(&CBTRECT, CBTRECTPTR, sizeof(RECT));
				//AddRECT(CBTRECT);
				break;
		}
	}
	return CallNextHookEx(CBT_HOOK_ID, nCode, wParam, lParam);  
}

bool SetCBTHook(DWORD ThreadID, HWND ThisMainWindow) {
	hWnd = ThisMainWindow;
	HHOOK CBT_HOOK_ID = ::SetWindowsHookEx(WH_CBT, CBTHookProc, 0, ThreadID);
	MessageBox(NULL, L"Hey", L"There", 1);
	if(CBT_HOOK_ID)
		return true;
	else
		return false;
}

void RemoveCBTHook() {
	UnhookWindowsHookEx(CBT_HOOK_ID);
} 

Its just a quick throw-together of setting a cbt hook on your window, the HookLib exports the hook function, allowing you to hook any process/the entire system.
Also note that the IsBadReadPtr is just there to ensure that the structure returned by the hook is valid, as sometimes it isnt causing the function to die.

Advertisements
28
Mar
09

[VB.net] Keyboard Hook Class

The keyboard hook from my old blog; “Low Level Keyboard Hook (Global) – Installing a Low Level Keyboard Hook”
This version is slightly updated, to cast the vkCode to the .net Keys enum to make key handling easier.

[16 June 2011 complete rewrite – should now work on every system -_-]

Imports System.Runtime.InteropServices

Public Class KeyboardHook

    <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
    Private Overloads Shared Function SetWindowsHookEx(ByVal idHook As Integer, ByVal HookProc As KBDLLHookProc, ByVal hInstance As IntPtr, ByVal wParam As Integer) As Integer
    End Function
    <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
    Private Overloads Shared Function CallNextHookEx(ByVal idHook As Integer, ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
    End Function
    <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
    Private Overloads Shared Function UnhookWindowsHookEx(ByVal idHook As Integer) As Boolean
    End Function

    <StructLayout(LayoutKind.Sequential)> _
    Private Structure KBDLLHOOKSTRUCT
        Public vkCode As UInt32
        Public scanCode As UInt32
        Public flags As KBDLLHOOKSTRUCTFlags
        Public time As UInt32
        Public dwExtraInfo As UIntPtr
    End Structure

    <Flags()> _
    Private Enum KBDLLHOOKSTRUCTFlags As UInt32
        LLKHF_EXTENDED = &H1
        LLKHF_INJECTED = &H10
        LLKHF_ALTDOWN = &H20
        LLKHF_UP = &H80
    End Enum

    Public Shared Event KeyDown(ByVal Key As Keys)
    Public Shared Event KeyUp(ByVal Key As Keys)

    Private Const WH_KEYBOARD_LL As Integer = 13
    Private Const HC_ACTION As Integer = 0
    Private Const WM_KEYDOWN = &H100
    Private Const WM_KEYUP = &H101
    Private Const WM_SYSKEYDOWN = &H104
    Private Const WM_SYSKEYUP = &H105

    Private Delegate Function KBDLLHookProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer

    Private KBDLLHookProcDelegate As KBDLLHookProc = New KBDLLHookProc(AddressOf KeyboardProc)
    Private HHookID As IntPtr = IntPtr.Zero

    Private Function KeyboardProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
        If (nCode = HC_ACTION) Then
            Dim struct As KBDLLHOOKSTRUCT
            Select Case wParam
                Case WM_KEYDOWN, WM_SYSKEYDOWN
                    RaiseEvent KeyDown(CType(CType(Marshal.PtrToStructure(lParam, struct.GetType()), KBDLLHOOKSTRUCT).vkCode, Keys))
                Case WM_KEYUP, WM_SYSKEYUP
                    RaiseEvent KeyUp(CType(CType(Marshal.PtrToStructure(lParam, struct.GetType()), KBDLLHOOKSTRUCT).vkCode, Keys))
            End Select
        End If
        Return CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam)
    End Function

    Public Sub New()
        HHookID = SetWindowsHookEx(WH_KEYBOARD_LL, KBDLLHookProcDelegate, System.Runtime.InteropServices.Marshal.GetHINSTANCE(System.Reflection.Assembly.GetExecutingAssembly.GetModules()(0)).ToInt32, 0)
        If HHookID = IntPtr.Zero Then
            Throw New Exception("Could not set keyboard hook")
        End If
    End Sub

    Protected Overrides Sub Finalize()
        If Not HHookID = IntPtr.Zero Then
            UnhookWindowsHookEx(HHookID)
        End If
        MyBase.Finalize()
    End Sub

End Class

Usage:
To create the hook

Private WithEvents kbHook As New KeyboardHook

Then each event can be handled:

Private Sub kbHook_KeyDown(ByVal Key As System.Windows.Forms.Keys) Handles kbHook.KeyDown Debug.WriteLine(Key.ToString) End Sub Private Sub kbHook_KeyUp(ByVal Key As System.Windows.Forms.Keys) Handles kbHook.KeyUp Debug.WriteLine(Key) End Sub

Note: To run this inside Visual Studio, you will need to go to:
Project -> [Project Name] Properties -> Debug -> Uncheck “Enable the Visual Studio hosting process”
As that intercepts the hooked messages before your program.

28
Mar
09

[VB.Net] Mouse Hook Class

An updated version of “Low Level Mouse Hook (Global) – Installing a Low Level Mouse Hook” from the old blog. Allows easier access to the events, as each has their own handler.

Private Class MouseHook
        Private Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Integer, ByVal lpfn As MouseProcDelegate, ByVal hmod As Integer, ByVal dwThreadId As Integer) As Integer
        Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Integer, ByVal nCode As Integer, ByVal wParam As Integer, ByVal lParam As MSLLHOOKSTRUCT) As Integer
        Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Integer) As Integer
        Private Delegate Function MouseProcDelegate(ByVal nCode As Integer, ByVal wParam As Integer, ByRef lParam As MSLLHOOKSTRUCT) As Integer

        Private Structure MSLLHOOKSTRUCT
            Public pt As Point
            Public mouseData As Integer
            Public flags As Integer
            Public time As Integer
            Public dwExtraInfo As Integer
        End Structure

        Public Enum Wheel_Direction
            WheelUp
            WheelDown
        End Enum

        Private Const HC_ACTION As Integer = 0
        Private Const WH_MOUSE_LL As Integer = 14
        Private Const WM_MOUSEMOVE As Integer = &H200
        Private Const WM_LBUTTONDOWN As Integer = &H201
        Private Const WM_LBUTTONUP As Integer = &H202
        Private Const WM_LBUTTONDBLCLK As Integer = &H203
        Private Const WM_RBUTTONDOWN As Integer = &H204
        Private Const WM_RBUTTONUP As Integer = &H205
        Private Const WM_RBUTTONDBLCLK As Integer = &H206
        Private Const WM_MBUTTONDOWN As Integer = &H207
        Private Const WM_MBUTTONUP As Integer = &H208
        Private Const WM_MBUTTONDBLCLK As Integer = &H209
        Private Const WM_MOUSEWHEEL As Integer = &H20A

        Private MouseHook As Integer
        Private MouseHookDelegate As MouseProcDelegate

        Public Event Mouse_Move(ByVal ptLocat As Point)
        Public Event Mouse_Left_Down(ByVal ptLocat As Point)
        Public Event Mouse_Left_Up(ByVal ptLocat As Point)
        Public Event Mouse_Left_DoubleClick(ByVal ptLocat As Point)
        Public Event Mouse_Right_Down(ByVal ptLocat As Point)
        Public Event Mouse_Right_Up(ByVal ptLocat As Point)
        Public Event Mouse_Right_DoubleClick(ByVal ptLocat As Point)
        Public Event Mouse_Middle_Down(ByVal ptLocat As Point)
        Public Event Mouse_Middle_Up(ByVal ptLocat As Point)
        Public Event Mouse_Middle_DoubleClick(ByVal ptLocat As Point)
        Public Event Mouse_Wheel(ByVal ptLocat As Point, ByVal Direction As Wheel_Direction)

        Public Sub New()
            MouseHookDelegate = New MouseProcDelegate(AddressOf MouseProc)
            MouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookDelegate, System.Runtime.InteropServices.Marshal.GetHINSTANCE(System.Reflection.Assembly.GetExecutingAssembly.GetModules()(0)).ToInt32, 0)
        End Sub

        Private Function MouseProc(ByVal nCode As Integer, ByVal wParam As Integer, ByRef lParam As MSLLHOOKSTRUCT) As Integer
            If (nCode = HC_ACTION) Then
                Select Case wParam
                    Case WM_MOUSEMOVE
                        RaiseEvent Mouse_Move(lParam.pt)
                    Case WM_LBUTTONDOWN
                        RaiseEvent Mouse_Left_Down(lParam.pt)
                    Case WM_LBUTTONUP
                        RaiseEvent Mouse_Left_Up(lParam.pt)
                    Case WM_LBUTTONDBLCLK
                        RaiseEvent Mouse_Left_DoubleClick(lParam.pt)
                    Case WM_RBUTTONDOWN
                        RaiseEvent Mouse_Right_Down(lParam.pt)
                    Case WM_RBUTTONUP
                        RaiseEvent Mouse_Right_Up(lParam.pt)
                    Case WM_RBUTTONDBLCLK
                        RaiseEvent Mouse_Right_DoubleClick(lParam.pt)
                    Case WM_MBUTTONDOWN
                        RaiseEvent Mouse_Middle_Down(lParam.pt)
                    Case WM_MBUTTONUP
                        RaiseEvent Mouse_Middle_Up(lParam.pt)
                    Case WM_MBUTTONDBLCLK
                        RaiseEvent Mouse_Middle_DoubleClick(lParam.pt)
                    Case WM_MOUSEWHEEL
                        Dim wDirection As Wheel_Direction
                        If lParam.mouseData < 0 Then
                            wDirection = Wheel_Direction.WheelDown
                        Else
                            wDirection = Wheel_Direction.WheelUp
                        End If
                        RaiseEvent Mouse_Wheel(lParam.pt, wDirection)
                End Select
            End If
            Return CallNextHookEx(MouseHook, nCode, wParam, lParam)
        End Function

        Protected Overrides Sub Finalize()
            UnhookWindowsHookEx(MouseHook)
            MyBase.Finalize()
        End Sub
    End Class

Usage:

   Private WithEvents mHook As New MouseHook

Since each mouse event raises its own event, you handle them like so:

    Private Sub mHook_Mouse_Left_DoubleClick(ByVal ptLocat As System.Drawing.Point) Handles mHook.Mouse_Left_DoubleClick
        Debug.WriteLine("Mouse Left Double Click At: (" & ptLocat.X & "," & ptLocat.Y & ")")
    End Sub

    Private Sub mHook_Mouse_Left_Down(ByVal ptLocat As System.Drawing.Point) Handles mHook.Mouse_Left_Down
        Debug.WriteLine("Mouse Left Down At: (" & ptLocat.X & "," & ptLocat.Y & ")")
    End Sub

    Private Sub mHook_Mouse_Left_Up(ByVal ptLocat As System.Drawing.Point) Handles mHook.Mouse_Left_Up
        Debug.WriteLine("Mouse Left Up At: (" & ptLocat.X & "," & ptLocat.Y & ")")
    End Sub

    Private Sub mHook_Mouse_Middle_DoubleClick(ByVal ptLocat As System.Drawing.Point) Handles mHook.Mouse_Middle_DoubleClick
        Debug.WriteLine("Mouse Middle Double Click At: (" & ptLocat.X & "," & ptLocat.Y & ")")
    End Sub

    Private Sub mHook_Mouse_Middle_Down(ByVal ptLocat As System.Drawing.Point) Handles mHook.Mouse_Middle_Down
        Debug.WriteLine("Mouse Middle Down At: (" & ptLocat.X & "," & ptLocat.Y & ")")
    End Sub

    Private Sub mHook_Mouse_Middle_Up(ByVal ptLocat As System.Drawing.Point) Handles mHook.Mouse_Middle_Up
        Debug.WriteLine("Mouse Middle Up At: (" & ptLocat.X & "," & ptLocat.Y & ")")
    End Sub

    Private Sub mHook_Mouse_Move(ByVal ptLocat As System.Drawing.Point) Handles mHook.Mouse_Move
        ''Will be called every time the mouse moves
    End Sub

    Private Sub mHook_Mouse_Right_DoubleClick(ByVal ptLocat As System.Drawing.Point) Handles mHook.Mouse_Right_DoubleClick
        Debug.WriteLine("Mouse Right Double Click At: (" & ptLocat.X & "," & ptLocat.Y & ")")
    End Sub

    Private Sub mHook_Mouse_Right_Down(ByVal ptLocat As System.Drawing.Point) Handles mHook.Mouse_Right_Down
        Debug.WriteLine("Mouse Right Down At: (" & ptLocat.X & "," & ptLocat.Y & ")")
    End Sub

    Private Sub mHook_Mouse_Right_Up(ByVal ptLocat As System.Drawing.Point) Handles mHook.Mouse_Right_Up
        Debug.WriteLine("Mouse Right Up At: (" & ptLocat.X & "," & ptLocat.Y & ")")
    End Sub

    Private Sub mHook_Mouse_Wheel(ByVal ptLocat As System.Drawing.Point, ByVal Direction As MouseHook.Wheel_Direction) Handles mHook.Mouse_Wheel
        Debug.WriteLine("Mouse Scroll: " & Direction.ToString & " At: (" & ptLocat.X & "," & ptLocat.Y & ")")
    End Sub

Note: To run this inside Visual Studio, you will need to go to:
Project -> [Project Name] Properties -> Debug -> Uncheck “Enable the Visual Studio hosting process”
As that intercepts the hooked messages before your program.