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

3 Responses to “[C++] CBT Hook Example”


  1. 1 Ron
    April 26, 2011 at 1:43 am

    Hi,
    This looks like an excellent example, except I can’t seem to build it in Visual C++.
    Is there a need to update it for the latest version or Visual C++ ?

    • 2 Tching
      March 2, 2012 at 9:37 am

      Hi,

      Same comment. I used VC++ Express 2010 and got this error :

      MSVCRTD.lib(crtexe.obj) : error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup

      • 3 sim0n
        March 12, 2012 at 4:12 pm

        Are you trying to compile this as a console program? Try changing the subsystem to windows:
        Project->properties->linker->system->subsystem


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: