home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Windoware
/
WINDOWARE_1_6.iso
/
source
/
adg_4-6
/
recorder.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-02-21
|
10KB
|
307 lines
/****************************************************************************
Module name: Recorder.C
Programmer : Jeffrey M. Richter.
*****************************************************************************/
#include "..\nowindws.h"
#undef NOCOLOR
#undef NOKERNEL
#undef NOMEMMGR
#undef NOMSG
#undef NOSHOWWINDOW
#undef NOUSER
#undef NOWH
#undef NOWINMESSAGES
#undef NOWINSTYLES
#include <windows.h>
#include "Recorder.h"
//****************************************************************************
static FARPROC _fnNextJrnlHookFunc = NULL;
static GLOBALHANDLE _hMemEvents = NULL;
static RECRESULT _PrematureHalt = REC_OK;
DWORD FAR PASCAL JrnlRecHookFunc (int nCode, WORD wParam, LPEVENTMSGMSG lpEventMsg);
DWORD FAR PASCAL JrnlPlybkHookFunc (int nCode, WORD wParam, LPEVENTMSGMSG lpEventMsg);
// Statistical information that appears at the beginning of the memory block.
typedef struct {
WORD wNumEvents, wNumEventsPlayed; DWORD dwStartTime;
} RECORDSTAT, FAR *LPRECORDSTAT;
BOOL FAR PASCAL LibMain (HANDLE hModule, WORD wDataSeg, WORD cbHeapSize, LPSTR lpCmdLine) {
if (cbHeapSize != 0) UnlockData(0); // Let data segment move
return(TRUE); // return TRUE if initialization is successful
}
int FAR PASCAL WEP (int nSystemExit) {
switch (nSystemExit) {
case WEP_SYSTEM_EXIT: // System is shutting down.
break;
case WEP_FREE_DLL: // Usage count is zero (0)
break;
}
return(1); // WEP function successful.
}
RECRESULT FAR PASCAL Recorder (RECORDMODE RecordMode, WORD wParam, LONG lParam) {
static HWND hWndNotify = NULL;
static WORD wMsgNotify = WM_NULL;
static RECORDMODE LastRecordMode = -1;
RECRESULT RecResult = REC_OK;
WORD wNumEvents;
LPRECORDSTAT lpRecordStat;
LPEVENTMSGMSG lpEvent;
switch (RecordMode) {
case RM_STARTRECORD:
// wParam: Not used.
// LOWORD(lParam): hWnd to end stop msg to.
// HIWORD(lParam): Message to send to hWnd.
// Returns: REC_ACTIVE, REC_NOMEMORY, REC_OK
if (_hMemEvents) { RecResult = REC_ACTIVE; break; }
// Save information so that it can be used by RM_STOPRECORD.
hWndNotify = (HWND) LOWORD(lParam);
wMsgNotify = (WORD) HIWORD(lParam);
// Assume the recording will be stopped by the user.
_PrematureHalt = REC_OK;
// Allocate memory block to hold the statistical data.
_hMemEvents = GlobalAlloc(GMEM_MOVEABLE, sizeof(RECORDSTAT));
if (_hMemEvents == NULL) { RecResult = REC_NOMEMORY; break; }
// Initialize the statistical data.
lpRecordStat = (LPRECORDSTAT) GlobalLock(_hMemEvents);
lpRecordStat->wNumEvents = lpRecordStat->wNumEventsPlayed = 0;
GlobalUnlock(_hMemEvents);
// Turn on the event recording.
_fnNextJrnlHookFunc =
SetWindowsHook(WH_JOURNALRECORD, (FARPROC) JrnlRecHookFunc);
RecResult = REC_OK;
break;
case RM_STOPRECORD:
// wParam: Not used.
// lParam: Not used.
// Returns: REC_INACTIVE, REC_OK
if (_hMemEvents == NULL) { RecResult = REC_INACTIVE; break; }
if (LastRecordMode == RM_STARTPLAY) { break; }
// Stop the recording of events.
UnhookWindowsHook(WH_JOURNALRECORD, (FARPROC) JrnlRecHookFunc);
// Modify all of the 'time' members in the EVENTMSG structures.
lpRecordStat = (LPRECORDSTAT) GlobalLock(_hMemEvents);
lpEvent = (LPEVENTMSGMSG) &lpRecordStat[1];
wNumEvents = lpRecordStat->wNumEvents;
while (wNumEvents > 1)
lpEvent[--wNumEvents].time -= lpEvent[0].time;
lpEvent[0].time = 0;
GlobalUnlock(_hMemEvents);
RecResult = REC_OK;
// Send message to specified window to notify it
// that recording has stopped.
SendMessage(hWndNotify, wMsgNotify, _hMemEvents, _PrematureHalt);
_hMemEvents = NULL;
break;
case RM_STARTPLAY:
// wParam: GLOBALHANDLE to macro
// lParam: LOWORD(lParam) = hWnd to end stop msg to.
// lParam: HIWORD(lParam) = Message to send to hWnd.
// Returns: REC_ACTIVE, REC_OK, REC_NOEVENTS
if (_hMemEvents != NULL) { RecResult = REC_ACTIVE; break; }
// Save information so that it can be used by RM_STOPRECORD.
hWndNotify = (HWND) LOWORD(lParam);
wMsgNotify = (WORD) HIWORD(lParam);
// Assume the playing will be stopped after all
// events have been played.
_PrematureHalt = REC_OK;
_hMemEvents = (GLOBALHANDLE) wParam;
// Initialize statistical data.
lpRecordStat = (LPRECORDSTAT) GlobalLock(_hMemEvents);
wNumEvents = lpRecordStat->wNumEvents;
lpRecordStat->wNumEventsPlayed = 0;
// Save the time when playback is started.
lpRecordStat->dwStartTime = GetTickCount();
GlobalUnlock(_hMemEvents);
if (wNumEvents == 0) { RecResult = REC_NOEVENTS; break; }
_fnNextJrnlHookFunc =
SetWindowsHook(WH_JOURNALPLAYBACK, (FARPROC) JrnlPlybkHookFunc);
break;
case RM_STOPPLAY:
// Stop playing the recorded events.
UnhookWindowsHook(WH_JOURNALPLAYBACK, (FARPROC) JrnlPlybkHookFunc);
_hMemEvents = NULL;
RecResult = REC_OK;
// Send message to specified window to notify it
// that playing has stopped.
SendMessage(hWndNotify, wMsgNotify, 0, _PrematureHalt);
break;
}
LastRecordMode = RecordMode;
return(RecResult);
}
DWORD FAR PASCAL JrnlRecHookFunc (int nCode, WORD wParam, LPEVENTMSGMSG lpEventMsg) {
static BOOL fPause = FALSE;
LPRECORDSTAT lpRecordStat;
LPEVENTMSGMSG lpEvent;
BOOL fCallDefProc = FALSE;
DWORD dwResult = 0;
WORD wNumEvents;
GLOBALHANDLE hMemTemp;
switch (nCode) {
case HC_ACTION:
fCallDefProc = TRUE;
// If a system-modal dialog box is up, don't record the event.
if (fPause) break;
// Determine the number of events in the memory block now.
lpRecordStat = (LPRECORDSTAT) GlobalLock(_hMemEvents);
wNumEvents = lpRecordStat->wNumEvents + 1;
GlobalUnlock(_hMemEvents);
if (wNumEvents == 0xffff) {
// Too many events recorded, stop recording.
_PrematureHalt = REC_TOOMANY;
Recorder(RM_STOPRECORD, 0, 0);
break;
}
// Increase the size of the memory block to hold the new event.
hMemTemp = GlobalReAlloc(_hMemEvents,
sizeof(RECORDSTAT) + wNumEvents * sizeof(EVENTMSG), GMEM_MOVEABLE);
if (hMemTemp == NULL) {
// Insufficient memory, stop recording.
_PrematureHalt = REC_NOMEMORY;
Recorder(RM_STOPRECORD, 0, 0);
break;
}
_hMemEvents = hMemTemp;
// Append the new event to the end of the memory block.
lpRecordStat = (LPRECORDSTAT) GlobalLock(_hMemEvents);
lpEvent = (LPEVENTMSGMSG) &lpRecordStat[1];
lpEvent[lpRecordStat->wNumEvents] = *lpEventMsg;
lpRecordStat->wNumEvents++;
GlobalUnlock(_hMemEvents);
break;
case HC_SYSMODALON:
// Stop recording events while the system-modal dialog box is up.
fPause = TRUE;
fCallDefProc = TRUE;
break;
case HC_SYSMODALOFF:
// The system-modal dialog box is gone, stop recording and
// notify the that recording has stopped.
fPause = FALSE;
_PrematureHalt = REC_SYSMODALON;
Recorder(RM_STOPRECORD, 0, 0);
break;
default:
fCallDefProc = TRUE;
break;
}
if (fCallDefProc)
dwResult = DefHookProc(nCode, wParam, (LONG) lpEventMsg,
(FARPROC FAR *) &_fnNextJrnlHookFunc);
return(dwResult);
}
DWORD FAR PASCAL JrnlPlybkHookFunc (int nCode, WORD wParam, LPEVENTMSGMSG lpEventMsg) {
BOOL fCallDefProc = FALSE;
DWORD dwResult = 0;
LPRECORDSTAT lpRecordStat;
LPEVENTMSGMSG lpEvent;
lpRecordStat = (LPRECORDSTAT) GlobalLock(_hMemEvents);
switch (nCode) {
case HC_SKIP:
// Prepare to return the next event the next time the hook code is
// HC_GETNEXT. If all events have been played, stop playing.
if (++lpRecordStat->wNumEventsPlayed == lpRecordStat->wNumEvents)
Recorder(RM_STOPPLAY, 0, 0);
break;
case HC_GETNEXT:
// Copy the current event to the EVENTMSG
// structure pointed to by lParam.
lpEvent = (LPEVENTMSGMSG) &lpRecordStat[1];
*lpEventMsg = lpEvent[lpRecordStat->wNumEventsPlayed];
// Adjust the 'time' by adding the time that playback started,
lpEventMsg->time += lpRecordStat->dwStartTime;
// Return the number of milliseconds Windows should wait
// before processing the event.
dwResult = lpEventMsg->time - GetTickCount();
// If the event occurred in the past, have Windows process it now.
if ((signed long) dwResult < 0) dwResult = 0;
break;
case HC_SYSMODALOFF:
// When the system-modal dialog box is removed, stop playing the
// events and notify the application.
_PrematureHalt = REC_SYSMODALON;
Recorder(RM_STOPPLAY, 0, 0);
fCallDefProc = TRUE;
break;
case HC_SYSMODALON:
default:
fCallDefProc = TRUE;
break;
}
GlobalUnlock(_hMemEvents);
if (fCallDefProc)
dwResult = DefHookProc(nCode, wParam, (LONG) lpEventMsg,
(FARPROC FAR *) &_fnNextJrnlHookFunc);
return(dwResult);
}