Annotation of q_a/samples/minrec/rechook.c, revision 1.1

1.1     ! root        1: // ************************************************************************
        !             2: //
        !             3: //                      Microsoft Developer Support
        !             4: //               Copyright (c) 1993 Microsoft Corporation
        !             5: //
        !             6: // ************************************************************************
        !             7: // MODULE    : RecHook.C
        !             8: // PURPOSE   : A Small Win32 Recorder-like Sample Application Hook DLL
        !             9: // FUNCTIONS :
        !            10: //   DllMain()            - Dll entry point (via _DLLMainCRTStartup)
        !            11: //   StartJournalRecord   - starts the journal record hook
        !            12: //   StopJournalRecord    - stops the journal record hook
        !            13: //   StartJournalPlayback - starts the journal playback hook
        !            14: //   StopJournalPlayback  - stops the journal playback hook
        !            15: //   StopAllJournalling   - stops any current journal hook
        !            16: // COMMENTS  : The Journal Record File contains an EVENTHEADER structure
        !            17: //             followed by a variable number of EVENTMSG structures.
        !            18: // ************************************************************************
        !            19: #define   STRICT               // strict type checking enabled
        !            20: #define   UNICODE              // make the application unicode complient
        !            21: #include <Windows.H>           // required for all Windows applications
        !            22: 
        !            23: #include "RecHook.H"
        !            24: #include "MinRec.H"            // we need IDM_MACRO_STOP
        !            25: 
        !            26: // Internal Defines
        !            27: // -----------------------------------------------------------------------
        !            28: #define MINREC_FILENAME  TEXT("MinRec.Rec") // File for record/play events
        !            29: #define MINREC_SIGNATURE "MinRec\0"         // Journal Record File signature
        !            30: 
        !            31: //-- header for the MinRec record/playback file
        !            32: typedef struct EVENTHEADER_STRUCT {
        !            33:   CHAR   Signature[7];
        !            34:   UINT   RecordedMsgCount;
        !            35:   DWORD  BaseMsgTime;
        !            36: } EVENTHEADER, *PEVENTHEADER;
        !            37: 
        !            38: //-- various "file global" data
        !            39: typedef struct GLOBAL_STRUCT {
        !            40:   BOOL      fRecording;
        !            41:   BOOL      fPlaying;
        !            42:   BOOL      fStopRecording;
        !            43:   BOOL      fStopPlaying;
        !            44:   UINT      PlayedMsgCount;
        !            45:   UINT      RecordedMsgCount;
        !            46:   DWORD     BaseMsgTime;
        !            47:   DWORD     LastMsgTime;
        !            48:   HANDLE    hFile;
        !            49:   EVENTMSG  EventMsg;
        !            50:   HHOOK     hHookRecord;
        !            51:   HHOOK     hHookPlayback;
        !            52:   HHOOK     hHookGetMsg;
        !            53:   HINSTANCE hInstance;
        !            54: } GLOBAL, *PGLOBAL;
        !            55: 
        !            56: // Global Data
        !            57: // -----------------------------------------------------------------------
        !            58: GLOBAL  Global;                // various global data
        !            59: 
        !            60: // Internal Function Prototypes
        !            61: // -----------------------------------------------------------------------
        !            62: LRESULT CALLBACK JournalRecordProc  ( int, WPARAM, LPARAM );
        !            63: LRESULT CALLBACK JournalPlaybackProc( int, WPARAM, LPARAM );
        !            64: LRESULT CALLBACK GetMsgProc         ( int, WPARAM, LPARAM );
        !            65: 
        !            66: 
        !            67: // ************************************************************************
        !            68: // FUNCTION : DllMain( HINSTANCE, DWORD, LPVOID )
        !            69: // PURPOSE  : DLLMain is called by the C run-time library from the
        !            70: //            _DLLMainCRTStartup entry point.  The DLL entry point gets
        !            71: //            called (entered) on the following events: "Process Attach",
        !            72: //            "Thread Attach", "Thread Detach" or "Process Detach".
        !            73: // ************************************************************************
        !            74: BOOL WINAPI
        !            75: DllMain( HINSTANCE hInstanceDll, DWORD dwReason, LPVOID lpvReserved )
        !            76: {
        !            77:   switch( dwReason ) {
        !            78: 
        !            79:     case DLL_PROCESS_ATTACH:
        !            80:       Global.fRecording    = FALSE;
        !            81:       Global.fPlaying      = FALSE;
        !            82:       Global.hInstance     = hInstanceDll;
        !            83:       break;
        !            84: 
        !            85:   }
        !            86: 
        !            87:   return( TRUE );
        !            88:   UNREFERENCED_PARAMETER( lpvReserved );
        !            89: }
        !            90: 
        !            91: 
        !            92: // ************************************************************************
        !            93: // FUNCTION : StartJournalRecord()
        !            94: // PURPOSE  : creates the record file and installs the record hook.
        !            95: // ************************************************************************
        !            96: BOOL
        !            97: StartJournalRecord()
        !            98: {
        !            99:   // Do not allow recording while playing back
        !           100:   if( Global.fPlaying ) {
        !           101:     MessageBox( GetFocus(),
        !           102:       TEXT( "Sorry, recording while\n" )
        !           103:       TEXT( "playing is not allowed."  ),
        !           104:       TEXT( "MinRec - Notice!"         ),
        !           105:       MB_ICONINFORMATION | MB_OK );
        !           106:     return( FALSE );
        !           107:   }
        !           108: 
        !           109:   // Create and open the journal record file and set the file pointer to
        !           110:   //  just past the journal record file header
        !           111:   Global.hFile = CreateFile( (LPCTSTR) MINREC_FILENAME, GENERIC_WRITE,
        !           112:                        0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
        !           113:   SetFilePointer( Global.hFile, (LONG) sizeof(EVENTHEADER), NULL,
        !           114:     FILE_BEGIN );
        !           115: 
        !           116:   // Initialize the recorded message count to zero and set recording flag
        !           117:   Global.RecordedMsgCount = 0;
        !           118:   Global.fRecording       = TRUE;
        !           119: 
        !           120:   // Set the GetMsg hook to trap Ctrl+Esc, Alt+Esc and Ctrl+Alt+Del.
        !           121:   Global.hHookGetMsg = SetWindowsHookEx( WH_GETMESSAGE, GetMsgProc,
        !           122:                          Global.hInstance, 0 );
        !           123: 
        !           124:   // Set the Journal Record hook.
        !           125:   Global.hHookRecord = SetWindowsHookEx( WH_JOURNALRECORD, JournalRecordProc,
        !           126:                          Global.hInstance, 0 );
        !           127: 
        !           128:   return( TRUE );
        !           129: }
        !           130: 
        !           131: 
        !           132: // ************************************************************************
        !           133: // FUNCTION : JournalRecordProc()
        !           134: // PURPOSE  : processes the journal record events by writing them to  the
        !           135: //            record file one event at a time.
        !           136: // ************************************************************************
        !           137: LRESULT CALLBACK
        !           138: JournalRecordProc( int nCode, WPARAM wParam, LPARAM lParam )
        !           139: {
        !           140:   if( nCode < 0 || Global.fStopRecording )
        !           141:     return( CallNextHookEx( Global.hHookRecord, nCode, wParam, lParam ) );
        !           142: 
        !           143:   switch( nCode ) {
        !           144: 
        !           145:     case HC_ACTION: {
        !           146:       LPEVENTMSG lpEventMsg;
        !           147:       DWORD      dwBytesWritten;
        !           148: 
        !           149:       lpEventMsg = (LPEVENTMSG) lParam;
        !           150: 
        !           151:       // user pressed Ctrl+Break to cancel journal recording
        !           152:       if( (lpEventMsg->message == WM_KEYDOWN)
        !           153:            && (LOBYTE(lpEventMsg->paramL) == VK_CANCEL) ) {
        !           154:         StopAllJournalling();
        !           155:       }
        !           156:       else {
        !           157:         // write the event message to the Recorded Journal file
        !           158:         WriteFile( Global.hFile, (LPCSTR) lParam, sizeof(EVENTMSG),
        !           159:           &dwBytesWritten, NULL );
        !           160:         lpEventMsg = (LPEVENTMSG) lParam;
        !           161:         Global.RecordedMsgCount++;
        !           162:         if( Global.RecordedMsgCount == 1)
        !           163:           Global.BaseMsgTime = lpEventMsg->time;
        !           164:       }
        !           165:       break;
        !           166:     }
        !           167: 
        !           168:     case HC_SYSMODALON:
        !           169:       // halt recording
        !           170:       Global.fStopRecording = TRUE;
        !           171:       break;
        !           172: 
        !           173:     case HC_SYSMODALOFF:
        !           174:       // resume recording
        !           175:       Global.fStopRecording = FALSE;
        !           176:       break;
        !           177: 
        !           178:   }
        !           179: 
        !           180:   return( CallNextHookEx( Global.hHookRecord, nCode, wParam, lParam ) );
        !           181:   UNREFERENCED_PARAMETER( wParam );
        !           182: }
        !           183: 
        !           184: 
        !           185: // ************************************************************************
        !           186: // FUNCTION : StopJournalRecord()
        !           187: // PURPOSE  : unhooks the record hook, records the record file header and
        !           188: //            closes the file.
        !           189: // ************************************************************************
        !           190: BOOL
        !           191: StopJournalRecord()
        !           192: {
        !           193:   EVENTHEADER EventHeader;
        !           194: 
        !           195:   // Remove the Journal Record hook if recording
        !           196:   if( Global.fRecording ) {
        !           197:     DWORD dwBytesWritten;
        !           198: 
        !           199:     // remove the record hook
        !           200:     UnhookWindowsHookEx( Global.hHookRecord );
        !           201: 
        !           202:     // remove the get message hook
        !           203:     UnhookWindowsHookEx( Global.hHookGetMsg );
        !           204: 
        !           205:     // Copy Recorded Journal header data to temporary buffer
        !           206:     lstrcpyA( EventHeader.Signature, MINREC_SIGNATURE );
        !           207:     EventHeader.RecordedMsgCount = Global.RecordedMsgCount;
        !           208:     EventHeader.BaseMsgTime      = Global.BaseMsgTime;
        !           209: 
        !           210:     // Open Recorded Journal file and update the file header and close
        !           211:     //  the file
        !           212:     SetFilePointer( Global.hFile, 0, NULL, FILE_BEGIN );
        !           213:     WriteFile( Global.hFile, (LPCSTR) &EventHeader, sizeof(EVENTHEADER),
        !           214:       &dwBytesWritten, NULL );
        !           215:     CloseHandle( Global.hFile );
        !           216: 
        !           217:     // Clear recording flag
        !           218:     Global.fRecording = FALSE;
        !           219:   }
        !           220: 
        !           221:   return( TRUE );
        !           222: }
        !           223: 
        !           224: 
        !           225: // ************************************************************************
        !           226: // FUNCTION : StartJournalPlayback()
        !           227: // PURPOSE  : opens the playback file and reads the header and installs the
        !           228: //            playback hook.
        !           229: // ************************************************************************
        !           230: BOOL
        !           231: StartJournalPlayback()
        !           232: {
        !           233:   EVENTHEADER EventHeader;
        !           234:   DWORD       dwBytesRead;
        !           235: 
        !           236:   // Allow infinite playback loop
        !           237:   if( Global.fRecording ) {
        !           238:     StopJournalRecord();
        !           239:     MessageBox( GetFocus(),
        !           240:       TEXT( "Infinite playback\n" )
        !           241:       TEXT( "loop recorded!"      ),
        !           242:       TEXT( "MinRec - Notice!"    ),
        !           243:       MB_ICONINFORMATION | MB_OK );
        !           244:     return( FALSE );
        !           245:   }
        !           246:   if( Global.fPlaying ) {
        !           247:     StopJournalPlayback();
        !           248:   }
        !           249: 
        !           250:   // Open Recorded Journal file
        !           251:   Global.hFile = CreateFile( (LPCTSTR) MINREC_FILENAME, GENERIC_READ,
        !           252:                        0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
        !           253:   if( Global.hFile == INVALID_HANDLE_VALUE ) {
        !           254:     MessageBox( GetFocus(),
        !           255:       TEXT( "The default Journal Record File\n" )
        !           256:       TEXT( "MINREC.REC could not be found.\n"  ),
        !           257:       TEXT( "MinRec - Error!"                   ),
        !           258:       MB_ICONEXCLAMATION | MB_OK );
        !           259:     return( FALSE );
        !           260:   }
        !           261: 
        !           262:   // Quick check, file size should be at least the length of the header
        !           263:   if( GetFileSize( Global.hFile, NULL ) < sizeof(EVENTHEADER) ) {
        !           264:     MessageBox( GetFocus(),
        !           265:       TEXT( "The file MINREC.REC is not a \n"     )
        !           266:       TEXT( "valid MinRec Journal Record file.\n" ),
        !           267:       TEXT( "MinRec - Error!"                     ),
        !           268:       MB_ICONEXCLAMATION | MB_OK );
        !           269:     return( FALSE );
        !           270:   }
        !           271: 
        !           272:   // Read Recorded Journal file header
        !           273:   SetFilePointer( Global.hFile, 0L, NULL, FILE_BEGIN );
        !           274:   ReadFile( Global.hFile, (LPVOID) &EventHeader, sizeof(EVENTHEADER),
        !           275:         &dwBytesRead, NULL );
        !           276: 
        !           277:   // Quick check, the signature of the file must be "MinRec"
        !           278:   if( lstrcmpA( EventHeader.Signature, MINREC_SIGNATURE ) != 0 ) {
        !           279:     MessageBox( GetFocus(),
        !           280:       TEXT( "The file MINREC.REC does not\n"    )
        !           281:       TEXT( "contain a valid MinRec signature." ),
        !           282:       TEXT( "MinRec - Error!"                   ),
        !           283:       MB_ICONEXCLAMATION | MB_OK );
        !           284:      return( FALSE );
        !           285:   }
        !           286: 
        !           287:   // store the header values
        !           288:   Global.RecordedMsgCount = EventHeader.RecordedMsgCount;
        !           289:   Global.BaseMsgTime      = EventHeader.BaseMsgTime;
        !           290:   Global.LastMsgTime      = EventHeader.BaseMsgTime;
        !           291: 
        !           292:   // If no messages were recorded, none to play back.
        !           293:   if( Global.RecordedMsgCount == 0 ) {
        !           294:     MessageBox( GetFocus(),
        !           295:       TEXT( "Sorry, nothing was recorded, so\n")
        !           296:       TEXT( "there is nothing to playback."    ),
        !           297:       TEXT( "MinRec - Notice!"                 ),
        !           298:       MB_ICONINFORMATION | MB_OK);
        !           299:      return( FALSE );
        !           300:   }
        !           301: 
        !           302:   // Initialize the played message count to zero and set the play flag
        !           303:   Global.PlayedMsgCount = 0;
        !           304:   Global.fPlaying       = TRUE;
        !           305: 
        !           306:   // Get the first recorded message from the file and store it
        !           307:   ReadFile( Global.hFile, (LPVOID) &(Global.EventMsg), sizeof(EVENTMSG),
        !           308:         &dwBytesRead, NULL );
        !           309: 
        !           310:   // Set the GetMsg hook to trap Ctrl+Break, Ctrl+Esc and Ctrl+Alt+Del.
        !           311:   Global.hHookGetMsg = SetWindowsHookEx( WH_GETMESSAGE, GetMsgProc,
        !           312:                          Global.hInstance, 0 );
        !           313: 
        !           314:   // Set the Journal Playback hook
        !           315:   Global.hHookPlayback = SetWindowsHookEx( WH_JOURNALPLAYBACK,
        !           316:                            JournalPlaybackProc, Global.hInstance, 0 );
        !           317: 
        !           318:  return( TRUE );
        !           319: }
        !           320: 
        !           321: 
        !           322: // ************************************************************************
        !           323: // FUNCTION : JournalPlaybackProc()
        !           324: // PURPOSE  : processes the journal playback events by reading in the
        !           325: //            playback file one event at a time.
        !           326: // ************************************************************************
        !           327: LRESULT CALLBACK
        !           328: JournalPlaybackProc( int nCode, WPARAM wParam, LPARAM lParam )
        !           329: {
        !           330:   if( nCode < 0  || Global.fStopPlaying )
        !           331:     return( CallNextHookEx( Global.hHookPlayback, nCode, wParam, lParam ) );
        !           332: 
        !           333:   switch( nCode ) {
        !           334: 
        !           335:    case HC_GETNEXT: {
        !           336:       LRESULT SleepTime = Global.EventMsg.time - Global.LastMsgTime;
        !           337: 
        !           338:       // copy the current ready event message to lParam
        !           339:       CopyMemory( (PVOID) lParam, (CONST VOID*) &(Global.EventMsg),
        !           340:         sizeof(EVENTMSG) );
        !           341:       Global.LastMsgTime = Global.EventMsg.time;
        !           342:       return( SleepTime );
        !           343:     }
        !           344: 
        !           345:     case HC_SKIP: {
        !           346:       if( ++Global.PlayedMsgCount > Global.RecordedMsgCount ) {
        !           347:         StopJournalPlayback();
        !           348:         return( (LRESULT) 0L );
        !           349:       }
        !           350:       else {
        !           351:         DWORD dwBytesRead;
        !           352: 
        !           353:         // Get the next recorded message from the file and store it
        !           354:         //  in the static buffer for the next HC_GETNEXT message
        !           355:         ReadFile( Global.hFile, (LPVOID) &(Global.EventMsg), sizeof(EVENTMSG),
        !           356:           &dwBytesRead, NULL );
        !           357:         break;
        !           358:       }
        !           359:     }
        !           360: 
        !           361:     case HC_SYSMODALON:
        !           362:       // halt playback
        !           363:       Global.fStopPlaying = TRUE;
        !           364:       break;
        !           365: 
        !           366:     case HC_SYSMODALOFF:
        !           367:       // resume playback
        !           368:       Global.fStopPlaying = FALSE;
        !           369:       break;
        !           370: 
        !           371:   }
        !           372: 
        !           373:   return( CallNextHookEx( Global.hHookPlayback, nCode, wParam, lParam ) );
        !           374:   UNREFERENCED_PARAMETER( wParam );
        !           375: }
        !           376: 
        !           377: 
        !           378: // ************************************************************************
        !           379: // FUNCTION : StopJournalPlayback()
        !           380: // PURPOSE  : unhooks the playback hook and closes the playback file.
        !           381: // ************************************************************************
        !           382: BOOL
        !           383: StopJournalPlayback()
        !           384: {
        !           385:   // Remove the Playback Journal hook if playing
        !           386:   if( Global.fPlaying ) {
        !           387: 
        !           388:     // remove the playback hook
        !           389:     UnhookWindowsHookEx( Global.hHookPlayback );
        !           390: 
        !           391:     // remove the get message hook
        !           392:     UnhookWindowsHookEx( Global.hHookGetMsg );
        !           393: 
        !           394:     // close the journal record file
        !           395:     CloseHandle( Global.hFile );
        !           396: 
        !           397:     // Clear playback flag
        !           398:     Global.fPlaying = FALSE;
        !           399:   }
        !           400: 
        !           401:  return( TRUE );
        !           402: }
        !           403: 
        !           404: 
        !           405: // ************************************************************************
        !           406: // FUNCTION : StopAllJournalling()
        !           407: // PURPOSE  : stops (unhooks) any current journal hook started (hooked) by
        !           408: //            this application.
        !           409: // ************************************************************************
        !           410: BOOL
        !           411: StopAllJournalling( )
        !           412: {
        !           413:  if( Global.fRecording )
        !           414:    StopJournalRecord();
        !           415:  if( Global.fPlaying )
        !           416:    StopJournalPlayback();
        !           417: 
        !           418:  return( TRUE );
        !           419: }
        !           420: 
        !           421: 
        !           422: // ************************************************************************
        !           423: // FUNCTION : GetMsgProc()
        !           424: // PURPOSE  : installs a get message hook to monitor messages sent to the
        !           425: //            queue so we can trap the WM_CANCELJOURNAL message send by the
        !           426: //            system when the user presses Ctrl+Esc, Alt+Esc or
        !           427: //            Ctrl+Alt+Del which cancels the journal hook.
        !           428: // COMMENTS : WM_CANCELJOURNAL gets sent to the thread which installs the
        !           429: //            hook but the hWnd of this message is NULL and thus does not
        !           430: //            get dispatched.   Thus this hook is used to retrieve this
        !           431: //            message.
        !           432: // ************************************************************************
        !           433: LRESULT CALLBACK
        !           434: GetMsgProc( int nCode, WPARAM wParam, LPARAM lParam )
        !           435: {
        !           436:   static LPMSG lpMsg;
        !           437: 
        !           438:   if( nCode < 0  )
        !           439:     return( CallNextHookEx( Global.hHookGetMsg, nCode, wParam, lParam ) );
        !           440: 
        !           441:   lpMsg = (LPMSG) lParam;
        !           442:   switch( lpMsg->message ) {
        !           443: 
        !           444:     // user pressed Ctrl+Esc, Alt+Esc or Ctrl+Alt+Del, the system will
        !           445:     // automatically stop all journalling.
        !           446:     case WM_CANCELJOURNAL:
        !           447:       StopAllJournalling();
        !           448:       MessageBox( GetFocus(),
        !           449:         TEXT( "The user has pressed either\n"            )
        !           450:         TEXT( "Ctrl+Esc, Alt+Esc or Ctrl+Alt+Del\n"      )
        !           451:         TEXT( "and thus the system has automatically\n"  )
        !           452:         TEXT( "canceled all journalling.\n"              ),
        !           453:         TEXT( "MinRec - Notice!"                         ),
        !           454:         MB_ICONINFORMATION | MB_OK );
        !           455:       break;
        !           456: 
        !           457:   }
        !           458: 
        !           459:   return( CallNextHookEx( Global.hHookGetMsg, nCode, wParam, lParam ) );
        !           460:   UNREFERENCED_PARAMETER( wParam );
        !           461: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.