|
// HookService.cpp
//
#include "stdafx.h"
#include "malloc.h"
#include "HookService.h"
HHOOK g_hHookRecorder= NULL;
HHOOK g_hHoohPlayBack= NULL;
S_ENODE *g_lpEventChain = NULL; // Head of recorded Event List
static S_ENODE *g_lpLastEvent = NULL; // Tail of recorded Event List
static S_ENODE *g_lpPlayEvent = NULL; // Current Event being played
static HWND g_hWndManager = NULL;
static BOOL g_fNoMouse = FALSE;
static BOOL g_fDoClear = FALSE;
static BOOL g_fSysModalOn = FALSE;
LRESULT CALLBACK JournalPlaybackFunc(int nCode, WPARAM wParam, LPARAM lParam );
LRESULT CALLBACK JournalRecorderFunc(int nCode, WPARAM wParam, LPARAM lParam );
///////////////////////////////////////////////////////////////////////////////////
void fnFreeAllEvents()
{
while(g_lpEventChain) {
S_ENODE* p= g_lpEventChain->lpNext;
free(g_lpEventChain);
g_lpEventChain = p;
}
g_lpLastEvent = g_lpPlayEvent = NULL;
}
int fnStartRecorder(HWND hWnd,BOOL fNoMouse)
{
if(g_hHookRecorder != 0)
return -1;
fnFreeAllEvents(); // zeroes g_lpEventChain, g_lpLastEvent, g_lpPlayEvent
g_hWndManager = hWnd;
g_fSysModalOn = FALSE;
g_fNoMouse = fNoMouse;
g_hHookRecorder= SetWindowsHookEx(WH_JOURNALRECORD, JournalRecorderFunc,
AfxGetInstanceHandle(), 0);
return 0;
}
int fnStop_Recorder(int nNotifyCode)
{
if(g_hHookRecorder == 0)
return -1;
UnhookWindowsHookEx(g_hHookRecorder);
g_hHookRecorder = NULL;
g_lpLastEvent = g_lpPlayEvent = NULL;
if(nNotifyCode != 0)
SendMessage(g_hWndManager, WM_SERVICE_INFO, SI_E_RC_STOP, nNotifyCode);
return 0;
}
int fnStartPlayBack(HWND hWnd,BOOL fDoClear)
{
if(g_hHoohPlayBack != 0)
return -1;
g_hWndManager = hWnd;
g_fSysModalOn = FALSE;
g_fDoClear = fDoClear;
g_lpLastEvent = g_lpPlayEvent = NULL;
g_hHoohPlayBack= SetWindowsHookEx(WH_JOURNALPLAYBACK, JournalPlaybackFunc,
AfxGetInstanceHandle(), 0);
return 0;
}
int fnStop_PlayBack(int nNotifyCode)
{
if(g_hHoohPlayBack == 0)
return -1;
UnhookWindowsHookEx(g_hHoohPlayBack);
g_hHoohPlayBack = NULL;
if(g_fDoClear)
fnFreeAllEvents();
if(nNotifyCode != 0)
SendMessage(g_hWndManager, WM_SERVICE_INFO, SI_E_PB_STOP, nNotifyCode);
return 0;
}
LRESULT CALLBACK JournalRecorderFunc(int nCode, WPARAM wParam, LPARAM lParam)
{
if(!g_hHookRecorder)
return 0;
if(nCode == HC_SYSMODALON)
g_fSysModalOn = TRUE;
else
if(nCode == HC_SYSMODALOFF)
g_fSysModalOn = FALSE;
else
if(nCode == HC_ACTION && g_hHoohPlayBack) { // Skip recording while playing back
fnStop_Recorder(SI_E_RC_SC_BUSY);
return 0;
}
if(nCode == HC_ACTION && !g_fSysModalOn) {
LPEVENTMSG lpEvent= (LPEVENTMSG)lParam;
// STOP - user stops recording by pressing CTRL+BREAK
if(lpEvent->message == WM_KEYDOWN && LOBYTE(lpEvent->paramL) == VK_CANCEL) {
fnStop_Recorder(SI_E_RC_SC_DONE);
return 0;
}
S_ENODE *lpEventNode= (S_ENODE*)malloc(sizeof(S_ENODE));
if(lpEventNode == NULL) { // Not enough memory
fnStop_Recorder(SI_E_RC_SC_MEMORY);
return 0;
}
if(g_lpLastEvent == NULL )
g_lpEventChain = lpEventNode;
else
g_lpLastEvent->lpNext = lpEventNode;
g_lpLastEvent = lpEventNode;
g_lpLastEvent->lpNext = NULL;
g_lpLastEvent->Event.message = lpEvent->message;
g_lpLastEvent->Event.paramL = lpEvent->paramL;
g_lpLastEvent->Event.paramH = lpEvent->paramH;
g_lpLastEvent->Event.time = GetTickCount();//lpEvent->time;
g_lpLastEvent->Event.hwnd = NULL;
// inform the manager about the message recorded
PostMessage(g_hWndManager, WM_SERVICE_INFO, SI_S_RC_EVENT, (LPARAM)g_lpLastEvent);
return 0;
}
return (CallNextHookEx(g_hHookRecorder, nCode, wParam, lParam));
}
LRESULT CALLBACK JournalPlaybackFunc (int nCode, WPARAM wParam, LPARAM lParam )
{
static S_ENODE *lpPrevPlayedEvent;
static DWORD dwLastEventTime;
static DWORD dwDelay= 0;
if(!g_hHoohPlayBack)
return 0;
if(nCode == HC_SYSMODALON)
g_fSysModalOn = TRUE;
else
if(nCode == HC_SYSMODALOFF)
g_fSysModalOn = FALSE;
else
if(nCode >= 0) {
if(g_lpEventChain == NULL) { // No any recorded records
fnStop_PlayBack(SI_E_PB_SC_EMPTY);
return 0;
}
if(g_hHookRecorder) { // Recording is running - abort playing
g_fDoClear = TRUE; // To prevent recorded events to be deleted
fnStop_PlayBack(SI_E_PB_SC_BUSY);
return ( (int)CallNextHookEx(g_hHoohPlayBack, nCode, wParam, lParam));
}
if(g_lpPlayEvent == NULL) { // First event is being played
dwDelay = 0;
g_lpPlayEvent = g_lpEventChain;
g_lpLastEvent = NULL; // For the next time we start the recorder
dwLastEventTime= g_lpPlayEvent->Event.time;
lpPrevPlayedEvent = NULL;
PostMessage(g_hWndManager, WM_SERVICE_INFO, SI_S_PB_START, (LPARAM)dwLastEventTime);
}
if(nCode == HC_SKIP) {
if(g_lpPlayEvent->lpNext == NULL) { // done recording
if(g_fDoClear) {
free(g_lpEventChain);
g_lpEventChain= NULL;
}
g_lpPlayEvent = g_lpLastEvent = NULL;
fnStop_PlayBack(SI_E_PB_SC_DONE);
} else {
dwDelay ++;
if(dwDelay == 0)
dwDelay = 1;
dwLastEventTime= g_lpPlayEvent->Event.time;
g_lpPlayEvent = g_lpPlayEvent->lpNext;
if(g_fDoClear) {
free(g_lpEventChain);
g_lpEventChain = g_lpPlayEvent;
}
PostMessage(g_hWndManager, WM_SERVICE_INFO, SI_S_PB_SKIP, 0);
}
return 0;
} else
if(nCode == HC_GETNEXT) {
LPEVENTMSG lpEvent= (LPEVENTMSG)lParam;
lpEvent->message = g_lpPlayEvent->Event.message;
lpEvent->paramL = g_lpPlayEvent->Event.paramL;
lpEvent->paramH = g_lpPlayEvent->Event.paramH;
lpEvent->time = g_lpPlayEvent->Event.time + GetTickCount();
long lReturnValue= 0;
if(dwDelay) {
dwDelay = 0;
lReturnValue = g_lpPlayEvent->Event.time - dwLastEventTime;
if(lReturnValue < 0L)
lReturnValue = 1L;
}
if(lReturnValue != 0)
PostMessage(g_hWndManager, WM_SERVICE_INFO, SI_S_PB_WAIT, lReturnValue);
else
if(lpPrevPlayedEvent != g_lpPlayEvent) {
PostMessage(g_hWndManager, WM_SERVICE_INFO, SI_S_PB_PLAY, (LPARAM)g_lpPlayEvent->Event.message);
lpPrevPlayedEvent = g_lpPlayEvent;
}
return lReturnValue;
}
}
return( CallNextHookEx(g_hHoohPlayBack, nCode, wParam, lParam));
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.