home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 18.ddi / SAMPLES / HOOKS / HOOKSDLL.C_ / HOOKSDLL.C
Encoding:
C/C++ Source or Header  |  1993-02-08  |  25.5 KB  |  829 lines

  1. //---------------------------------------------------------------------------
  2. //  Windows hooks Sample Application - The DLL
  3. //
  4. //  This sample application demonstrates how to use Windows hooks.
  5. //
  6. //  This File contains the source code for the hooksdll
  7. //
  8. //  Author:    Kyle Marsh
  9. //              Windows Developer Technology Group
  10. //              Microsoft Corp.
  11. //
  12. //---------------------------------------------------------------------------
  13.  
  14.  
  15. #include "windows.h"
  16. #include "string.h"
  17. #include "hooks.h"
  18.  
  19. //---------------------------------------------------------------------------
  20. // Function declarations
  21. //---------------------------------------------------------------------------
  22.  
  23. int   __export CALLBACK LibMain(HANDLE hModule, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine);
  24. int   __export CALLBACK _WEP (int bSystemExit);
  25. int   __export CALLBACK InitHooksDll(HWND hwndMainWindow, int nWinLineHeight);
  26. int   __export CALLBACK PaintHooksDll(HDC hDC );
  27. int   __export CALLBACK InstallFilter (int nHookIndex, int nCode );
  28. void  __export CALLBACK CallWndProcFunc (int nCode, WORD wParam, DWORD lParam );
  29. int   __export CALLBACK CbtFunc (int nCode, WORD wParam, DWORD lParam );
  30. void  __export CALLBACK GetMessageFunc (int nCode, WORD wParam, DWORD lParam );
  31. DWORD __export CALLBACK JournalPlaybackFunc (int nCode, WORD wParam, DWORD lParam );
  32. void  __export CALLBACK JournalRecordFunc (int nCode, WORD wParam, DWORD lParam );
  33. int   __export CALLBACK KeyboardFunc (int nCode, WORD wParam, DWORD lParam );
  34. int   __export CALLBACK MouseFunc (int nCode, WORD wParam, DWORD lParam );
  35. int   __export CALLBACK SysMsgFilterFunc (int nCode, WORD wParam, DWORD lParam );
  36. char  FAR *szMessageString(WORD wID);
  37.  
  38. //---------------------------------------------------------------------------
  39. // Global Variables...
  40. //---------------------------------------------------------------------------
  41.  
  42. HANDLE    hInstance;        // Global instance handle for  DLL
  43. HWND    hwndMain;        // Main hwnd. We will get this from the App
  44. int    InitCalled = 0;     // Has the Init function been called ?
  45. int    nLineHeight;        // Heigth of lines in window
  46. char    szType[64];        // A Place to write temporary strings
  47. int    nRecordedEvents = -1;    // Number or Events Recorded
  48. DWORD    dwStartRecordTime;    // Time JournalRecord Started
  49.  
  50. typedef struct TAGEventNode {
  51.        EVENTMSG         Event;
  52.     struct TAGEventNode FAR *lpNextEvent;
  53. } EventNode;
  54.  
  55. EventNode FAR *lpEventChain  = NULL;  // Head of recorded Event List
  56. EventNode FAR *lpLastEvent   = NULL;  // Tail of recorded Event List
  57. EventNode FAR *lpPlayEvent   = NULL;  // Current Event being played
  58.  
  59. //
  60. //  My Hook States
  61. //
  62. int HookStates[NUMOFHOOKS] = { 0,0,0,0,0,0,0,0,0 } ; // State Table of my hooks
  63.  
  64. //
  65. //  Hook Codes
  66. //
  67. int HookCodes[NUMOFHOOKS] = {
  68.                    WH_CALLWNDPROC,
  69.                    WH_CBT,
  70.                    WH_GETMESSAGE,
  71.                    WH_JOURNALPLAYBACK,
  72.                    WH_JOURNALRECORD,
  73.                    WH_KEYBOARD,
  74.                    WH_MOUSE,
  75.                    WH_MSGFILTER,
  76.                    WH_SYSMSGFILTER
  77.                 };
  78.  
  79. //
  80. // Filter Function Addresses
  81. //
  82. FARPROC lpfnHookProcs[NUMOFHOOKS] = {
  83.                       (FARPROC) CallWndProcFunc,
  84.                       (FARPROC) CbtFunc,
  85.                       (FARPROC) GetMessageFunc,
  86.                       (FARPROC) JournalPlaybackFunc,
  87.                       (FARPROC) JournalRecordFunc,
  88.                       (FARPROC) KeyboardFunc,
  89.                       (FARPROC) MouseFunc,
  90.                       NULL,
  91.                       (FARPROC) SysMsgFilterFunc,
  92.                     };
  93.  
  94. //
  95. // Hook Handles
  96. //
  97. HHOOK hhookHooks[NUMOFHOOKS];
  98.  
  99. //
  100. // Output Lines
  101. //
  102. char szFilterLine[NUMOFHOOKS][128];
  103.  
  104. //---------------------------------------------------------------------------
  105. // LibMain
  106. //---------------------------------------------------------------------------
  107. int __export CALLBACK LibMain(HANDLE hModule, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine)
  108. {
  109.     hInstance = hModule;
  110.     return 1;
  111. }
  112.  
  113. #pragma alloc_text(FIXEDSEG, _WEP)
  114.  
  115. //---------------------------------------------------------------------------
  116. // WEP
  117. //---------------------------------------------------------------------------
  118. int __export CALLBACK _WEP (int bSystemExit)
  119. {
  120.     return(1);
  121. }
  122.  
  123.  
  124.  
  125. //---------------------------------------------------------------------------
  126. // InitHooksDll
  127. //---------------------------------------------------------------------------
  128. int __export CALLBACK InitHooksDll(HWND hwndMainWindow, int nWinLineHeight)
  129. {
  130.     hwndMain = hwndMainWindow;
  131.     nLineHeight = nWinLineHeight;
  132.  
  133.  
  134.     InitCalled = 1;
  135.     return (0);
  136. }
  137.  
  138.  
  139. //---------------------------------------------------------------------------
  140. // PaintHooksDll
  141. //---------------------------------------------------------------------------
  142. int __export CALLBACK PaintHooksDll(HDC hDC )
  143. {
  144.    int i;
  145.  
  146.    for (i = 0; i < NUMOFHOOKS; i++ ) {
  147.        if ( HookCodes[i] != WH_MSGFILTER && HookStates[i] )
  148.        TabbedTextOut(hDC, 1, nLineHeight * i,
  149.         (LPSTR)szFilterLine[i], strlen(szFilterLine[i]), 0, NULL, 1);
  150.    }
  151.  
  152.    return (0);
  153. }
  154.  
  155. //---------------------------------------------------------------------------
  156. // InstallSysMsgFilter
  157. //
  158. // Install / Remove Filter function for the WH_SYSMSGFILTER
  159. //
  160. //---------------------------------------------------------------------------
  161. int __export CALLBACK InstallFilter (int nHookIndex, int nCode )
  162. {
  163.  
  164.      if ( ! InitCalled ) {
  165.     return (-1);
  166.      }
  167.      if ( nCode ) {
  168.     hhookHooks[nHookIndex] =
  169.           SetWindowsHookEx(HookCodes[nHookIndex], (HOOKPROC) lpfnHookProcs[nHookIndex], hInstance,NULL);
  170.     HookStates[nHookIndex] = TRUE;
  171.      }
  172.      else {
  173.     UnhookWindowsHookEx(hhookHooks[nHookIndex]);
  174.     HookStates[nHookIndex] = FALSE;
  175.     InvalidateRect(hwndMain, NULL, TRUE);
  176.     UpdateWindow(hwndMain);
  177.      }
  178. }
  179.  
  180. //---------------------------------------------------------------------------
  181. // CallWndProcFunc
  182. //
  183. // Filter function for the WH_CALLWNDPROC
  184. //
  185. //---------------------------------------------------------------------------
  186. void __export CALLBACK CallWndProcFunc (int nCode, WORD wParam, DWORD lParam )
  187. {
  188.    HDC           hDC;
  189.    // structure used for CallWpnProc
  190.    struct tempStruct
  191.      {
  192.        LONG       lParam;
  193.        WORD       wParam;
  194.        WORD       message;
  195.        HWND       hwnd;
  196.      } FAR * lptsParamStruct;
  197.  
  198.  
  199.    if ( nCode >= 0 ) {
  200.  
  201.       lptsParamStruct = (struct tempStruct FAR *) lParam;
  202.  
  203.       if ( wParam )
  204.      _fstrcpy(szType,"From Current Task");
  205.       else
  206.      _fstrcpy(szType," ");
  207.  
  208.       wsprintf((LPSTR)szFilterLine[CALLWNDPROCINDEX],
  209.            "CALLWNDPROC\tWnd:%d\t%s %s                    ",
  210.            lptsParamStruct->hwnd,
  211.            szMessageString(lptsParamStruct->message), (LPSTR)szType);
  212.  
  213.       hDC = GetDC(hwndMain);
  214.       TabbedTextOut(hDC, 1, nLineHeight * CALLWNDPROCINDEX,
  215.         (LPSTR)szFilterLine[CALLWNDPROCINDEX],
  216.         strlen(szFilterLine[CALLWNDPROCINDEX]), 0, NULL, 1);
  217.       ReleaseDC(hwndMain, hDC);
  218.  
  219.    }
  220.  
  221.    //
  222.    // We looked at the message ... sort of processed it but since we are
  223.    // looking we will pass all messages on to CallNextHookEx.
  224.    //
  225.    CallNextHookEx(hhookHooks[CALLWNDPROCINDEX], nCode, (WORD)wParam,(WORD) lParam);
  226.    return;
  227. }
  228.  
  229. //---------------------------------------------------------------------------
  230. // CbtFunc
  231. //
  232. // Filter function for the WH_CBT
  233. //
  234. //---------------------------------------------------------------------------
  235. int __export CALLBACK CbtFunc (int nCode, WORD wParam, DWORD lParam )
  236. {
  237.    HDC           hDC;
  238.    CBTACTIVATESTRUCT FAR *Active;
  239.    LPMOUSEHOOKSTRUCT MouseHookParam;
  240.    LPCBT_CREATEWND   CreateWndParam;
  241.    LPRECT         Rect;
  242.  
  243.    if ( nCode >= 0 ) {
  244.       switch ( nCode ) {
  245.       case HCBT_ACTIVATE:
  246.          Active = (CBTACTIVATESTRUCT FAR *) lParam;
  247.          wsprintf((LPSTR)szFilterLine[CBTINDEX],
  248.           "CBT\t\tGoing to Activate Wnd:%d Wnd:%d is active. Mouse Flag:%d                      ",
  249.           wParam,Active->hWndActive,Active->fMouse);
  250.  
  251.          break;
  252.  
  253.       case HCBT_CLICKSKIPPED:
  254.          MouseHookParam = (LPMOUSEHOOKSTRUCT) lParam;
  255.          wsprintf((LPSTR)szFilterLine[CBTINDEX],
  256.           "CBT\t\tMouse Message Removed from Queue. Point:%d %d %s                              ",
  257.           MouseHookParam->pt.x,MouseHookParam->pt.y,
  258.           szMessageString(wParam));
  259.  
  260.          break;
  261.  
  262.       case HCBT_CREATEWND:
  263.          CreateWndParam = (LPCBT_CREATEWND) lParam;
  264.          wsprintf((LPSTR)szFilterLine[CBTINDEX],
  265.           "CBT\t\tGoing to Create Wnd:%d %s                                                     ",
  266.           wParam,CreateWndParam->lpcs->lpszName);
  267.  
  268.          break;
  269.  
  270.       case HCBT_DESTROYWND:
  271.          wsprintf((LPSTR)szFilterLine[CBTINDEX],
  272.           "CBT\t\tGoing to Destroy Wnd:%d                                                       ",
  273.           wParam);
  274.  
  275.          break;
  276.  
  277.       case HCBT_KEYSKIPPED:
  278.          wsprintf((LPSTR)szFilterLine[CBTINDEX],
  279.           "CBT\t\tKeyboard Message Removed from Queue. Key:%d                                   ",
  280.           wParam);
  281.  
  282.          break;
  283.  
  284.       case HCBT_MINMAX:
  285.          switch ( LOWORD(lParam) ) {
  286.          case SW_HIDE:
  287.             _fstrcpy(szType, "SW_HIDE");
  288.             break;
  289.  
  290.          case SW_NORMAL:
  291.             _fstrcpy(szType, "SW_NORMAL");
  292.             break;
  293.  
  294.          case SW_SHOWMINIMIZED:
  295.             _fstrcpy(szType, "SW_SHOWMINIMIZED");
  296.             break;
  297.  
  298.          case SW_MAXIMIZE:
  299.             _fstrcpy(szType, "SW_MAXIMIZE");
  300.             break;
  301.  
  302.          case SW_SHOWNOACTIVATE:
  303.             _fstrcpy(szType, "SW_SHOWNOACTIVATE");
  304.             break;
  305.  
  306.          case SW_SHOW:
  307.             _fstrcpy(szType, "SW_SHOW");
  308.             break;
  309.  
  310.          case SW_MINIMIZE:
  311.             _fstrcpy(szType, "SW_MINIMIZE");
  312.             break;
  313.  
  314.          case SW_SHOWMINNOACTIVE:
  315.             _fstrcpy(szType, "SW_SHOWMINNOACTIVE");
  316.             break;
  317.  
  318.          case SW_SHOWNA:
  319.             _fstrcpy(szType, "SW_SHOWNA");
  320.             break;
  321.  
  322.          case SW_RESTORE:
  323.             _fstrcpy(szType, "SW_RESTORE");
  324.             break;
  325.  
  326.          default:
  327.             _fstrcpy(szType,"Unknown Message");
  328.  
  329.          }
  330.          wsprintf((LPSTR)szFilterLine[CBTINDEX],
  331.           "CBT\t\tGoing to MIN/MAX Wnd:%d %s                                                    ",
  332.           wParam,(LPSTR)szType);
  333.  
  334.          break;
  335.  
  336.       case HCBT_MOVESIZE:
  337.          Rect = (LPRECT) lParam;
  338.          wsprintf((LPSTR)szFilterLine[CBTINDEX],
  339.           "CBT\t\tGoing to MOVE/SIZE Wnd:%d to %d %d %d %d                                      ",
  340.           wParam,Rect->left,Rect->top,Rect->right,Rect->bottom);
  341.  
  342.          break;
  343.  
  344.       case HCBT_QS:
  345.          wsprintf((LPSTR)szFilterLine[CBTINDEX],
  346.           "CBT\t\tWM_QUEUESYNC Message                                                          ");
  347.  
  348.          break;
  349.  
  350.       case HCBT_SETFOCUS:
  351.          wsprintf((LPSTR)szFilterLine[CBTINDEX],
  352.           "CBT\t\tGiving Focus to Wnd:%d Taking Focus From Wnd:%d                               ",
  353.           wParam,LOWORD(lParam));
  354.  
  355.          break;
  356.  
  357.       case HCBT_SYSCOMMAND:
  358.          switch ( wParam ) {
  359.           case SC_SIZE:
  360.              _fstrcpy(szType,"SC_SIZE");
  361.              break;
  362.  
  363.           case SC_MOVE:
  364.              _fstrcpy(szType,"SC_MOVE");
  365.              break;
  366.  
  367.           case SC_MINIMIZE:
  368.              _fstrcpy(szType,"SC_MINIMIZE");
  369.              break;
  370.  
  371.           case SC_MAXIMIZE:
  372.              _fstrcpy(szType,"SC_MAXIMIZE");
  373.              break;
  374.  
  375.           case SC_NEXTWINDOW:
  376.              _fstrcpy(szType,"SC_NEXTWINDOW");
  377.              break;
  378.  
  379.           case SC_PREVWINDOW:
  380.              _fstrcpy(szType,"SC_PREVWINDOW");
  381.              break;
  382.  
  383.           case SC_CLOSE:
  384.              _fstrcpy(szType,"SC_CLOSE");
  385.              break;
  386.  
  387.           case SC_VSCROLL:
  388.              _fstrcpy(szType,"SC_VSCROLL");
  389.              break;
  390.  
  391.           case SC_HSCROLL:
  392.              _fstrcpy(szType,"SC_HSCROLL");
  393.              break;
  394.  
  395.           case SC_MOUSEMENU:
  396.              _fstrcpy(szType,"SC_MOUSEMENU");
  397.              break;
  398.  
  399.           case SC_KEYMENU:
  400.              _fstrcpy(szType,"SC_KEYMENU");
  401.              break;
  402.  
  403.           case SC_ARRANGE:
  404.              _fstrcpy(szType,"SC_ARRANGE");
  405.              break;
  406.  
  407.           case SC_RESTORE:
  408.              _fstrcpy(szType,"SC_RESTORE");
  409.              break;
  410.  
  411.           case SC_TASKLIST:
  412.              _fstrcpy(szType,"SC_TASKLIST");
  413.              break;
  414.  
  415.           case SC_SCREENSAVE:
  416.              _fstrcpy(szType,"SC_SCREENSAVE");
  417.              break;
  418.  
  419.           case SC_HOTKEY:
  420.              _fstrcpy(szType,"SC_HOTKEY");
  421.              break;
  422.  
  423.          default:
  424.             _fstrcpy(szType,"Unknown Message");
  425.  
  426.          }
  427.          wsprintf((LPSTR)szFilterLine[CBTINDEX],
  428.           "CBT\t\tAbout to Perform System Command: %s                                           ",
  429.           (LPSTR)szType);
  430.  
  431.          break;
  432.  
  433.       }
  434.  
  435.       hDC = GetDC(hwndMain);
  436.       TabbedTextOut(hDC, 1, nLineHeight * CBTINDEX,
  437.         (LPSTR)szFilterLine[CBTINDEX],
  438.         strlen(szFilterLine[CBTINDEX]), 0, NULL, 1);
  439.       ReleaseDC(hwndMain, hDC);
  440.    }
  441.  
  442.    //
  443.    // We looked at the message ... sort of processed it but since we are
  444.    // looking we will pass all messages on to CallNextHookEx.
  445.    //
  446.    return( (int)CallNextHookEx(hhookHooks[CBTINDEX], nCode,(WORD)wParam,(WORD) lParam));
  447. }
  448.  
  449. //---------------------------------------------------------------------------
  450. // GetMessageFunc
  451. //
  452. // Filter function for the WH_GETMESSAGE
  453. //
  454. //---------------------------------------------------------------------------
  455. void __export CALLBACK GetMessageFunc (int nCode, WORD wParam, DWORD lParam )
  456. {
  457.    MSG FAR *lpMsg;
  458.    HDC       hDC;
  459.  
  460.    if ( nCode >= 0 ) {
  461.       lpMsg = (MSG FAR *) lParam;
  462.       wsprintf((LPSTR)szFilterLine[GETMESSAGEINDEX],
  463.            "GETMESSAGE\tWnd:%d Time:%ld  Point:%d %d %s                                  ",
  464.            lpMsg->hwnd, lpMsg->time,
  465.            lpMsg->pt.x, lpMsg->pt.y, szMessageString(lpMsg->message));
  466.  
  467.  
  468.       hDC = GetDC(hwndMain);
  469.       TabbedTextOut(hDC, 1, nLineHeight * GETMESSAGEINDEX,
  470.         (LPSTR)szFilterLine[GETMESSAGEINDEX],
  471.         strlen(szFilterLine[GETMESSAGEINDEX]), 0, NULL, 1);
  472.       ReleaseDC(hwndMain, hDC);
  473.    }
  474.  
  475.    //
  476.    // We looked at the message ... sort of processed it but since we are
  477.    // looking we will pass all messages on to CallNextHookEx.
  478.    //
  479.    CallNextHookEx(hhookHooks[GETMESSAGEINDEX], nCode, wParam, lParam);
  480.    return;
  481. }
  482.  
  483. //---------------------------------------------------------------------------
  484. // JournalPlaybackFunc
  485. //
  486. // Filter function for the WH_JOURNALPLAYBACK
  487. //
  488. //---------------------------------------------------------------------------
  489. DWORD __export CALLBACK JournalPlaybackFunc (int nCode, WORD wParam, DWORD lParam )
  490. {
  491.    HDC         hDC;
  492.    static int     nRepeatRequests;
  493.    HANDLE     hEvent;
  494.    LPEVENTMSG lpEvent;
  495.    static DWORD  dwTimeAdjust;
  496.    long      lReturnValue;
  497.    static DWORD  dwLastEventTime;
  498.    HMENU     hMenu;
  499.  
  500.    if ( nCode >= 0 ) {
  501.       // No Playback if we haven't recorded an Event
  502.       //
  503.       // No Playback While recording.
  504.       // This is not a limitation of the hooks.
  505.       // This is only because of the simple event storage used in this example
  506.       //
  507.       // We should never get here since the enable / disable menu stuff should
  508.       // make getting here impossible
  509.       //
  510.       if ( lpEventChain == NULL || HookStates[JOURNALRECORDINDEX]) {
  511.       InstallFilter(JOURNALPLAYBACKINDEX, FALSE);
  512.       hMenu = GetMenu(hwndMain);
  513.       CheckMenuItem(hMenu, IDM_JOURNALPLAYBACK, MF_UNCHECKED | MF_BYCOMMAND);
  514.       EnableMenuItem(hMenu, IDM_JOURNALPLAYBACK, MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);
  515.       wsprintf((LPSTR)szFilterLine[JOURNALPLAYBACKINDEX],
  516.           "WH_JOURNALPLAYBACK -- No recorded Events to Playback  or JournalRecord in Progress                  ");
  517.       hDC = GetDC(hwndMain);
  518.       TabbedTextOut(hDC, 1, nLineHeight * JOURNALPLAYBACKINDEX,
  519.         (LPSTR)szFilterLine[JOURNALPLAYBACKINDEX],
  520.         strlen(szFilterLine[JOURNALPLAYBACKINDEX]), 0, NULL, 1);
  521.       ReleaseDC(hwndMain, hDC);
  522.           return( (int)CallNextHookEx(hhookHooks[JOURNALPLAYBACKINDEX], nCode, wParam, lParam ));
  523.       }
  524.  
  525.       if ( lpPlayEvent == NULL ) {
  526.      lpPlayEvent = lpEventChain;
  527.      lpLastEvent = NULL;       // For the next time we start the recorder
  528.      dwTimeAdjust = GetTickCount() - dwStartRecordTime;
  529.      dwLastEventTime = (DWORD) GetTickCount();
  530.      nRepeatRequests = 1;
  531.       }
  532.  
  533.       if (nCode == HC_SKIP ) {
  534.       nRepeatRequests = 1;
  535.  
  536.       if ( lpPlayEvent->lpNextEvent == NULL ) {
  537.           wsprintf((LPSTR)szFilterLine[JOURNALPLAYBACKINDEX],
  538.               "WH_JOURNALPLAYBACK -- Done Recorded Events");
  539.           hDC = GetDC(hwndMain);
  540.           TabbedTextOut(hDC, 1, nLineHeight * JOURNALPLAYBACKINDEX,
  541.             (LPSTR)szFilterLine[JOURNALPLAYBACKINDEX],
  542.             strlen(szFilterLine[JOURNALPLAYBACKINDEX]), 0, NULL, 1);
  543.           ReleaseDC(hwndMain, hDC);
  544.  
  545.           hEvent = (HANDLE)LOWORD(GlobalHandle((HIWORD(lpEventChain))));
  546.           GlobalUnlock(hEvent);
  547.           GlobalFree(hEvent);
  548.           lpEventChain = lpPlayEvent = NULL ;
  549.  
  550.           InstallFilter(JOURNALPLAYBACKINDEX, FALSE);
  551.           hMenu = GetMenu(hwndMain);
  552.           CheckMenuItem(hMenu, IDM_JOURNALPLAYBACK, MF_UNCHECKED | MF_BYCOMMAND);
  553.           EnableMenuItem(hMenu, IDM_JOURNALPLAYBACK, MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);
  554.       }
  555.       else {
  556.           dwLastEventTime = lpPlayEvent->Event.time;
  557.           lpPlayEvent = lpPlayEvent->lpNextEvent;
  558.  
  559.           hEvent = (HANDLE)LOWORD(GlobalHandle((HIWORD(lpEventChain))));
  560.           GlobalUnlock(hEvent);
  561.           GlobalFree(hEvent);
  562.           lpEventChain = lpPlayEvent;
  563.       }
  564.       }
  565.       else if ( nCode == HC_GETNEXT) {
  566.       lpEvent = (LPEVENTMSG) lParam;
  567.       lpEvent->message = lpPlayEvent->Event.message;
  568.       lpEvent->paramL  = lpPlayEvent->Event.paramL;
  569.       lpEvent->paramH  = lpPlayEvent->Event.paramH;
  570.       lpEvent->time    = lpPlayEvent->Event.time + dwTimeAdjust;
  571.  
  572.       wsprintf((LPSTR)szFilterLine[JOURNALPLAYBACKINDEX],
  573.            "WH_JOURNALPLAYBACK -- Playing Event %d times                    ",
  574.            nRepeatRequests++);
  575.       hDC = GetDC(hwndMain);
  576.       TabbedTextOut(hDC, 1, nLineHeight * JOURNALPLAYBACKINDEX,
  577.         (LPSTR)szFilterLine[JOURNALPLAYBACKINDEX],
  578.         strlen(szFilterLine[JOURNALPLAYBACKINDEX]), 0, NULL, 1);
  579.       ReleaseDC(hwndMain, hDC);
  580.  
  581.       lReturnValue = lpEvent->time - GetTickCount();
  582.       //
  583.       // No Long ( negative ) waits
  584.       //
  585.       if ( lReturnValue < 0L ) {
  586.          lReturnValue  = 0L;
  587.          lpEvent->time = GetTickCount();
  588.       }
  589.       return ( (DWORD) lReturnValue );
  590.       }
  591.  
  592.       hDC = GetDC(hwndMain);
  593.       TabbedTextOut(hDC, 1, nLineHeight * JOURNALPLAYBACKINDEX,
  594.         (LPSTR)szFilterLine[JOURNALPLAYBACKINDEX],
  595.         strlen(szFilterLine[JOURNALPLAYBACKINDEX]), 0, NULL, 1);
  596.       ReleaseDC(hwndMain, hDC);
  597.    }
  598.  
  599.    return( (int)CallNextHookEx(hhookHooks[JOURNALPLAYBACKINDEX], nCode, wParam, lParam));
  600. }
  601.  
  602. //---------------------------------------------------------------------------
  603. // JournalRecordFunc
  604. //
  605. // Filter function for the WH_JOURNALRECORD
  606. //
  607. //---------------------------------------------------------------------------
  608. void __export CALLBACK JournalRecordFunc (int nCode, WORD wParam, DWORD lParam )
  609. {
  610.    HDC       hDC;
  611.    HANDLE      hEvent;
  612.    EventNode FAR *lpEventNode;
  613.    LPEVENTMSG  lpEvent;
  614.    HMENU      hMenu;
  615.  
  616.    if ( nCode >= 0 ) {
  617.  
  618.       lpEvent = (LPEVENTMSG) lParam;
  619.       //
  620.       // Skip recording while playing back
  621.       // This is not a limitation of the hooks.
  622.       // This is only because of the simple event storage used in this example
  623.       //
  624.       if ( HookStates[JOURNALPLAYBACKINDEX] ) {
  625.      wsprintf((LPSTR)szFilterLine[JOURNALRECORDINDEX],
  626.            "WH_JOURNALRECORD\tSkipping Recording during Playback                        ");
  627.      hDC = GetDC(hwndMain);
  628.      TabbedTextOut(hDC, 1, nLineHeight * JOURNALRECORDINDEX,
  629.            (LPSTR)szFilterLine[JOURNALRECORDINDEX],
  630.            strlen(szFilterLine[JOURNALRECORDINDEX]), 0, NULL, 1);
  631.      ReleaseDC(hwndMain, hDC);
  632.      return;
  633.       }
  634.  
  635.       //
  636.       // Stop recording ?
  637.       //
  638.       if ( lpEvent->message == WM_KEYDOWN &&
  639.        LOBYTE(lpEvent->paramL)  == VK_F2 ) {
  640.      wsprintf((LPSTR)szFilterLine[JOURNALRECORDINDEX],
  641.            "WH_JOURNALRECORD\tRecording Stopped with F2                                                                 ");
  642.      InstallFilter(JOURNALRECORDINDEX, FALSE);
  643.      hMenu = GetMenu(hwndMain);
  644.      CheckMenuItem(hMenu, IDM_JOURNALRECORD, MF_UNCHECKED | MF_BYCOMMAND);
  645.      EnableMenuItem(hMenu, IDM_JOURNALPLAYBACK, MF_ENABLED | MF_BYCOMMAND);
  646.      return ;
  647.       }
  648.  
  649.       if ((hEvent=
  650.       GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE,sizeof(EventNode))) == NULL ) {
  651.      wsprintf((LPSTR)szFilterLine[JOURNALRECORDINDEX],
  652.            "WH_JOURNALRECORD\tNo Memory Available");
  653.      InstallFilter(JOURNALRECORDINDEX, FALSE);
  654.      hMenu = GetMenu(hwndMain);
  655.      CheckMenuItem(hMenu, IDM_JOURNALRECORD, MF_UNCHECKED | MF_BYCOMMAND);
  656.      EnableMenuItem(hMenu, IDM_JOURNALPLAYBACK, MF_ENABLED | MF_BYCOMMAND);
  657.      return;
  658.       }
  659.       if ( (lpEventNode = (EventNode FAR *)GlobalLock(hEvent)) == NULL ) {
  660.      GlobalFree(hEvent);
  661.      wsprintf((LPSTR)szFilterLine[JOURNALRECORDINDEX],
  662.            "WH_JOURNALRECORD\tNo Memory Available");
  663.      InstallFilter(JOURNALRECORDINDEX, FALSE);
  664.      hMenu = GetMenu(hwndMain);
  665.      CheckMenuItem(hMenu, IDM_JOURNALRECORD, MF_UNCHECKED | MF_BYCOMMAND);
  666.      EnableMenuItem(hMenu, IDM_JOURNALPLAYBACK, MF_ENABLED | MF_BYCOMMAND);
  667.       }
  668.  
  669.  
  670.       if ( lpLastEvent == NULL ) {
  671.      dwStartRecordTime = (DWORD) GetTickCount();
  672.      lpEventChain = lpEventNode;
  673.       }
  674.       else {
  675.      lpLastEvent->lpNextEvent = lpEventNode;
  676.       }
  677.  
  678.       lpLastEvent = lpEventNode;
  679.       lpLastEvent->lpNextEvent = NULL;
  680.  
  681.       lpLastEvent->Event.message = lpEvent->message;
  682.       lpLastEvent->Event.paramL  = lpEvent->paramL;
  683.       lpLastEvent->Event.paramH  = lpEvent->paramH;
  684.       lpLastEvent->Event.time     = lpEvent->time;
  685.  
  686.  
  687.       wsprintf((LPSTR)szFilterLine[JOURNALRECORDINDEX],
  688.         "WH_JOURNALRECORD\tRecording\tTime:%ld\tPRESS F2 To Stop Recording\t%s                        ",
  689.         lpEvent->time,szMessageString(lpEvent->message));
  690.       hDC = GetDC(hwndMain);
  691.       TabbedTextOut(hDC, 1, nLineHeight * JOURNALRECORDINDEX,
  692.         (LPSTR)szFilterLine[JOURNALRECORDINDEX],
  693.         strlen(szFilterLine[JOURNALRECORDINDEX]), 0, NULL, 1);
  694.       ReleaseDC(hwndMain, hDC);
  695.       return;
  696.    }
  697.  
  698.    CallNextHookEx(hhookHooks[JOURNALRECORDINDEX], nCode, wParam, lParam);
  699.    return;
  700. }
  701.  
  702. //---------------------------------------------------------------------------
  703. // KeyboardFunc
  704. //
  705. // Filter function for the WH_KEYBOARD
  706. //
  707. //---------------------------------------------------------------------------
  708. int __export CALLBACK KeyboardFunc (int nCode, WORD wParam, DWORD lParam )
  709. {
  710.    HDC           hDC;
  711.  
  712.    if ( nCode >= 0 ) {
  713.  
  714.       if ( nCode == HC_NOREMOVE )
  715.      _fstrcpy(szType, "NOT Removed from Queue");
  716.       else
  717.      _fstrcpy(szType, "REMOVED from Queue                                             ");
  718.  
  719.       wsprintf((LPSTR)szFilterLine[KEYBOARDINDEX],
  720.            "KEYBOARD\tKey:%d\t%s",wParam,(LPSTR)szType);
  721.  
  722.       hDC = GetDC(hwndMain);
  723.       TabbedTextOut(hDC, 1, nLineHeight * KEYBOARDINDEX,
  724.         (LPSTR)szFilterLine[KEYBOARDINDEX],
  725.         strlen(szFilterLine[KEYBOARDINDEX]), 0, NULL, 1);
  726.       ReleaseDC(hwndMain, hDC);
  727.    }
  728.  
  729.    //
  730.    // We looked at the message ... sort of processed it but since we are
  731.    // looking we will pass all messages on to CallNextHookEx.
  732.    //
  733.    return( (int)CallNextHookEx(hhookHooks[KEYBOARDINDEX], nCode, wParam, lParam));
  734. }
  735.  
  736. //---------------------------------------------------------------------------
  737. // MouseFunc
  738. //
  739. // Filter function for the WH_MOUSE
  740. //
  741. //---------------------------------------------------------------------------
  742. int __export CALLBACK MouseFunc (int nCode, WORD wParam, DWORD lParam )
  743. {
  744.    HDC           hDC;
  745.    LPMOUSEHOOKSTRUCT MouseHookParam;
  746.  
  747.    if ( nCode >= 0 ) {
  748.       if ( nCode == HC_NOREMOVE )
  749.      _fstrcpy(szType, "NOT Removed from Queue");
  750.       else
  751.      _fstrcpy(szType, "REMOVED from Queue                                             ");
  752.  
  753.       MouseHookParam = (MOUSEHOOKSTRUCT FAR *) lParam;
  754.  
  755.       wsprintf((LPSTR)szFilterLine[MOUSEINDEX],
  756.           "MOUSE\t\tWnd:%d Point:%d %d\t%s %s",MouseHookParam->hwnd,
  757.           MouseHookParam->pt.x,MouseHookParam->pt.y,
  758.           szMessageString(wParam),(LPSTR)szType);
  759.  
  760.       hDC = GetDC(hwndMain);
  761.       TabbedTextOut(hDC, 1, nLineHeight * MOUSEINDEX,
  762.         (LPSTR)szFilterLine[MOUSEINDEX], strlen(szFilterLine[MOUSEINDEX]),
  763.         0, NULL, 1 );
  764.       ReleaseDC(hwndMain, hDC);
  765.  
  766.    }
  767.  
  768.    //
  769.    // We looked at the message ... sort of processed it but since we are
  770.    // looking we will pass all messages on to CallNextHookEx.
  771.    //
  772.    return( (int)CallNextHookEx(hhookHooks[MOUSEINDEX], nCode, wParam, lParam));
  773. }
  774.  
  775. //---------------------------------------------------------------------------
  776. // SysMsgFilterFunc
  777. //
  778. // Filter function for the WH_SYSMSGFILTER
  779. //
  780. //---------------------------------------------------------------------------
  781. int __export CALLBACK SysMsgFilterFunc (int nCode, WORD wParam, DWORD lParam )
  782. {
  783.    MSG FAR *lpMsg;
  784.    HDC           hDC;
  785.  
  786.    if ( nCode >= 0 ) {
  787.       if ( nCode == MSGF_DIALOGBOX )
  788.      _fstrcpy(szType,"Dialog");
  789.       else
  790.      _fstrcpy(szType,"Menu");
  791.  
  792.       lpMsg = (MSG FAR *) lParam;
  793.       wsprintf((LPSTR)szFilterLine[SYSMSGFILTERINDEX],
  794.            "SYSMSGFILTER\t%s\tWnd:%d Time:%ld  Point:%d %d %s                                ",
  795.            (LPSTR)szType, lpMsg->hwnd, lpMsg->time,
  796.            lpMsg->pt.x, lpMsg->pt.y, szMessageString(lpMsg->message));
  797.  
  798.       hDC = GetDC(hwndMain);
  799.       TabbedTextOut(hDC, 1, nLineHeight * SYSMSGFILTERINDEX,
  800.         (LPSTR)szFilterLine[SYSMSGFILTERINDEX],
  801.         strlen(szFilterLine[SYSMSGFILTERINDEX]), 0, NULL, 1 );
  802.       ReleaseDC(hwndMain, hDC);
  803.    }
  804.  
  805.    //
  806.    // We looked at the message ... sort of processed it but since we are
  807.    // looking we will pass all messages on to CallNextHookEx.
  808.    //
  809.    return( (int)CallNextHookEx(hhookHooks[SYSMSGFILTERINDEX], nCode, wParam, lParam));
  810. }
  811.  
  812.  
  813. //---------------------------------------------------------------------------
  814. // MessageString
  815. //
  816. // Function to load string from the STRINGTABLE
  817. //
  818. //---------------------------------------------------------------------------
  819. char FAR * szMessageString(WORD wID)
  820. {
  821.    static char szBuffer[256];
  822.  
  823.    if ( LoadString(hInstance, wID, szBuffer, 255) == 0)
  824.       _fstrcpy(szBuffer,"Unknown Message");
  825.  
  826.    return (szBuffer);
  827.  
  828. }
  829.