현재 CE에서 후킹에 관한 API는 undocument되어 있습니다.
하지만 coredll.dll에 SetWindowsHookExW, UnhookWindowsHookEx, CallNextHookEx, QASetWindowsJournalHook, QAUnhookWindowsJournalHook 함수가 익스포트 되어 있습니다.
CE에서 SetWindowsHookExW는 키보드 메시지만 후킹이 가능하지만 QASetWindowsJournalHook을 사용하면 마우스 메시지까지 후킹을 할 수 있습니다.
여러환경에서 철저하게 테스트를 거친 소스가 아니기 때문에 앞으로 발생할 문제점에 대해서는 책임지지 않겠습니다. ㅎ ^^;;
적당히 디버깅 용도로 사용하기에는 괜찮을 것 같습니다.
일반적인 글로벌(흐름 제어) 후킹은 DLL로 작성하면 되지만 Journal Hooking 방식은 해당 스레드의 컨텍스트에서만 유효하기 때문에 다른 방식을 사용해야 합니다. 기타 후킹에 대한 아키텍쳐 및 작성 방법은 MSDN 또는 구글을 참조하세요.
다음은 TestHooking.cpp 소스에 있는 주요 내용입니다.
#define WH_JOURNALRECORD 0
#define WH_JOURNALPLAYBACK 1
#define WH_KEYBOARD_LL 20
#define HC_ACTION 0
#define HC_GETNEXT 1
#define HC_SKIP 2
#define HC_NOREMOVE 3
#define HC_NOREM HC_NOREMOVE
#define HC_SYSMODALON 4
#define HC_SYSMODALOFF 5
// Keyboard
typedef LRESULT (WINAPI* HOOKPROC)(int, WPARAM, LPARAM);
typedef HHOOK (WINAPI* SETWINDOWSHOOKEX)(int, HOOKPROC, HINSTANCE, DWORD);
typedef BOOL (WINAPI* UNHOOKWINDOWSHOOKEX)(HHOOK);
typedef LRESULT (WINAPI* CALLNEXTHOOKEX)(HHOOK, int , WPARAM, LPARAM);
typedef struct {
DWORD vkCode;
DWORD scanCode;
DWORD flags;
DWORD time;
ULONG_PTR dwExtraInfo;
} KBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT;
// Journal
typedef struct {
UINT message;
UINT paramL;
UINT paramH;
DWORD time;
HWND hwnd;
} EVENTMSG, *PEVENTMSG;
typedef HHOOK (WINAPI*QASETWINDOWSJOURNALHOOK)(int, LPVOID, EVENTMSG*);
typedef HHOOK (WINAPI*QAUNHOOKWINDOWSJOURNALHOOK)(int);
HMODULE g_hCore;
HHOOK g_hKeyHook;
HHOOK g_hJournalHook;
EVENTMSG g_event;
SETWINDOWSHOOKEX SetWindowsHookEx;
UNHOOKWINDOWSHOOKEX UnhookWindowsHookEx;
CALLNEXTHOOKEX CallNextHookEx;
QASETWINDOWSJOURNALHOOK QASetWindowsJournalHook;
QAUNHOOKWINDOWSJOURNALHOOK QAUnhookWindowsJournalHook;
LRESULT CALLBACK KeyHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if( nCode == HC_ACTION )
{
PKBDLLHOOKSTRUCT key = (PKBDLLHOOKSTRUCT)lParam;
TRACE(_T("KeyHookProc => message(%d:0x%x), vkey(%d:0x%x)n"), wParam, wParam, key->vkCode, key->vkCode);
}
return CallNextHookEx(g_hKeyHook, nCode, wParam, lParam);
}
LRESULT CALLBACK JournalHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if( nCode >= 0 )
{
EVENTMSG *pEvent = (EVENTMSG*)lParam;
TRACE(_T("JournalHookProc => message(%d:0x%x), hwnd(0x%x)n"), pEvent->message, pEvent->message, pEvent->hwnd);
}
return CallNextHookEx(g_hJournalHook, nCode, wParam, lParam);
}
BOOL CTestHookingApp::InitInstance()
{
g_hCore = GetModuleHandle(L"coredll.dll");
SetWindowsHookEx = (SETWINDOWSHOOKEX)GetProcAddress(g_hCore, L"SetWindowsHookExW");
UnhookWindowsHookEx = (UNHOOKWINDOWSHOOKEX)GetProcAddress(g_hCore, L"UnhookWindowsHookEx");
CallNextHookEx = (CALLNEXTHOOKEX)GetProcAddress(g_hCore, L"CallNextHookEx");
QASetWindowsJournalHook = (QASETWINDOWSJOURNALHOOK)GetProcAddress(g_hCore, L"QASetWindowsJournalHook");
QAUnhookWindowsJournalHook = (QAUNHOOKWINDOWSJOURNALHOOK)GetProcAddress(g_hCore, L"QAUnhookWindowsJournalHook");
g_hKeyHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)KeyHookProc, theApp.m_hInstance, 0);
g_hJournalHook = QASetWindowsJournalHook(WH_JOURNALRECORD, JournalHookProc, &g_event);
...
...
...
return FALSE;
}
int CTestHookingApp::ExitInstance()
{
QAUnhookWindowsJournalHook(WH_JOURNALRECORD);
UnhookWindowsHookEx(g_hKeyHook);
return CWinApp::ExitInstance();
}