Guest User

Untitled

a guest
Jun 18th, 2018
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.83 KB | None | 0 0
  1. /* Copyright 2000 by Symantec Corporation--------------------------------------
  2.  
  3.  File : LowLevelKeyHook.cpp
  4.  
  5.  Purpose : Install a hook prior to the system window procedure to catch
  6.  Alt+Tab, Shift+Alt+Tab, Alt+Esc, Ctrl+Esc
  7.  
  8.  Author: E. Feldl, July 2000
  9. ----------------------------------------------------------------------------- */
  10.  
  11. // Must be before stdafx.h. Necessary for compile. We later poll the OS to
  12. // determine if we should run NT/2000 or 98 code.
  13. #define _WIN32_WINNT  0x0400
  14.  
  15. #include <afxwin.h>        // AfxGetInstanceHandle();
  16. #include <windows.h>
  17. #include <winuser.h>
  18.  
  19. #include "lowlevelkeyhook.h"
  20. #include "globdefs.h"      // #define TERMWINDOW_CLASS_NAME (LPSTR)"TERMWindow"
  21.  
  22. HHOOK CurrentHook  = NULL; // necessary for LowLevelKeyboardProc
  23. int   MajorVersion = 0;
  24.  
  25. /* -----------------------------------------------------------------------------
  26. Routine:    "PreSysWndProcKeyHook"
  27.  
  28. Purpose:    Install the windows hook and register the custom messages.
  29.  
  30. Parameter            Type           Description
  31. ---------            ----           -----------
  32. NONE
  33.  
  34. Initializer          Type           Description
  35. -----------          ----           -----------
  36. m_Hook               HHOOK          Current Window Hook
  37.  
  38. Creation Date: July 2000, E. Feldl
  39. ----------------------------------------------------------------------------- */
  40. PreSysWndProcKeyHook::PreSysWndProcKeyHook() : m_Hook(NULL)
  41. {
  42.  
  43.     // Please note that WH_KEYBOARD_LL used in SetWindowsHookEx is only valid
  44.     // on Windows NT 4.0 Service Pack 3 or greater. This also serves as a
  45.     // placeholder were code for other operating systems can be added.
  46.     IsNTVersion4OrHigher(MajorVersion);
  47.  
  48.     if((MajorVersion == 4 && GetServicePack() >= 3)|| MajorVersion >= 5)
  49.     {
  50.         // Please note that RegisterWindowsMessage can perform two functions.
  51.         // It can return a new unique message id or it can look up and existing
  52.         // id. Therefor registering the same call twice does not result in
  53.         // multiple identifiers.
  54.         RegisterWindowMessage(CTRL_ESC_MSG);
  55.         RegisterWindowMessage(ALT_ESC_MSG);
  56.         RegisterWindowMessage(BRINGUPTASKSWITCHER_MSG);
  57.         RegisterWindowMessage(TABNEXTTASK_MSG);
  58.  
  59.         // Do not install the hook unless this is NT4 SP3.
  60.         m_Hook = InstallWindowHook();
  61.  
  62.         // We should pass in our current hook into CallNextHookEx and since
  63.         // LowLevelKeyboardProc must be a C function, we need this global
  64.         // to store it's value.
  65.         CurrentHook = m_Hook;
  66.  
  67.     }
  68. }
  69. /* -----------------------------------------------------------------------------
  70. Routine:    "~PreSysWndProcKeyHook"
  71.  
  72. Purpose:    Uninstall the hook.
  73.  
  74. Parameter            Type           Description
  75. ---------            ----           -----------
  76. NONE
  77.  
  78. Creation Date: July 2000, E. Feldl
  79. ----------------------------------------------------------------------------- */
  80. PreSysWndProcKeyHook::~PreSysWndProcKeyHook()
  81. {
  82.     // No need to call UnhookWindowsHookEx unless we installed the Hook. This
  83.     // also serves as a placeholder for code for other operating systems.
  84.     if((MajorVersion == 4 && GetServicePack() >= 3)|| MajorVersion >= 5)
  85.     {
  86.         UnhookWindowsHookEx(m_Hook);
  87.         CurrentHook = NULL;
  88.     }
  89.  
  90. }
  91. /* -----------------------------------------------------------------------------
  92. Routine:    "InstallWindowHook"
  93.  
  94. Purpose:    Wrap SetWindowsHookEx with checking.
  95.  
  96. Parameter            Type           Description
  97. ---------            ----           -----------
  98. NONE
  99.  
  100. Returns              Type           Description
  101. ---------            ----           -----------
  102. hHook                HHOOK          Current Window Hook
  103.  
  104. Creation Date: July 2000, E. Feldl
  105. ----------------------------------------------------------------------------- */
  106. HHOOK PreSysWndProcKeyHook::InstallWindowHook()
  107. {
  108.     HHOOK hHook = SetWindowsHookEx(WH_KEYBOARD_LL,
  109.                                    LowLevelKeyboardProc,
  110.                                    AfxGetInstanceHandle(),
  111.                                    0);
  112.     ASSERT(hHook != NULL);
  113.  
  114.     return hHook;
  115. }
  116. /* -----------------------------------------------------------------------------
  117. Routine:    "IsNTVersion4OrHigher"
  118.  
  119. Purpose:
  120.  
  121.     Check to see if this is NT 4.0 or greater. WH_KEYBOARD_LL is only valid on
  122.     these systems.
  123.  
  124. Parameter            Type                 Description
  125. ---------            ----                 -----------
  126. version              integer reference    Used to return the major version number
  127.  
  128. Returns              Type                 Description
  129. ---------            ----                 -----------
  130.                      BOOL                 True if NT4, False otherwise
  131.  
  132. Creation Date: July 2000, E. Feldl
  133. ----------------------------------------------------------------------------- */
  134. BOOL PreSysWndProcKeyHook::IsNTVersion4OrHigher(int &version)
  135. {
  136.     OSVERSIONINFO os;
  137.     os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  138.  
  139.     GetVersionEx(&os);
  140.  
  141.     if(os.dwPlatformId == VER_PLATFORM_WIN32_NT &&
  142.        os.dwMajorVersion >= 4 )
  143.     {
  144.         version = os.dwMajorVersion;
  145.         return TRUE;
  146.     }
  147.     else
  148.     {
  149.         version = 0;
  150.         return FALSE;
  151.     }
  152. }
  153. /* -----------------------------------------------------------------------------
  154. Routine:    "LowLevelKeyboardProc"
  155.  
  156. Purpose:    The "C" hook function to install.
  157.  
  158. Parameter            Type               Description
  159. ---------            ----               -----------
  160. nCode                int                Hook code passed to hook procedure
  161. wParam               WPARAM             Custom messages wParam == NULL
  162. lParam               LPARAM             Custom messages lParam == NULL
  163.  
  164. Returns              Type               Description
  165. ---------            ----               -----------
  166.                      LRESULT CALLBACK   Windows Callback Function
  167.  
  168. Creation Date: July 2000, E. Feldl
  169. ----------------------------------------------------------------------------- */
  170. LRESULT CALLBACK PreSysWndProcKeyHook::LowLevelKeyboardProc(int nCode,
  171.                                                             WPARAM wParam,
  172.                                                             LPARAM lParam)
  173. {
  174.     // Allow us to disable CallNextHookEx
  175.     BOOL   fEatKeystroke            = FALSE;
  176.     // Handle to our terminal window
  177.     HWND   hFindWnd                 = NULL;
  178.     // Used to toggle Alt+Tab, Tab, Tab .... in task switcher
  179.     static BOOL RanOnce             = FALSE;
  180.  
  181.     //  Is the scroll key toggled on?
  182.     BOOL ScrollLocked = GetKeyState(VK_SCROLL) & 0x0001;
  183.  
  184.     // If Scroll not locked don't handle.
  185.     if((nCode == HC_ACTION) && ScrollLocked)
  186.     {
  187.         // Stores the low level keyboard event information.
  188.         PKBDLLHOOKSTRUCT pInfoLowLevelEvent = (PKBDLLHOOKSTRUCT)lParam;
  189.  
  190.         // hFindWnd must be correct or else PostMessage
  191.         // won't go to correct window proc.
  192.         hFindWnd = FindWindow(TERMWINDOW_CLASS_NAME,NULL);
  193.        
  194.         // If our window isn't the active one, we shouldn't capture keys.
  195.         if(hFindWnd != GetForegroundWindow())
  196.         {
  197.             return CallNextHookEx(CurrentHook, nCode, wParam, lParam);
  198.         }
  199.    
  200.         // We must have a window to send the messages to.
  201.         ASSERT(hFindWnd != NULL);
  202.  
  203.         //if(wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)
  204.         switch(wParam)
  205.         {
  206.             case WM_KEYDOWN: case WM_SYSKEYDOWN:
  207.             // Yes we are interested in these keys
  208.        
  209.             // ALT-DOWN+TAB-DOWN
  210.             if((pInfoLowLevelEvent->vkCode==VK_TAB)&&
  211.                ((pInfoLowLevelEvent->flags&LLKHF_ALTDOWN)!=0))
  212.             {
  213.  
  214.                 if(RanOnce == FALSE)
  215.                 {
  216.                    // We need to bring up the task switcher.
  217.                    SendCustomMessage(hFindWnd,
  218.                              RegisterWindowMessage(BRINGUPTASKSWITCHER_MSG));
  219.                    fEatKeystroke = TRUE;
  220.                    RanOnce =TRUE;
  221.                 }
  222.                 else
  223.                 {
  224.                    // We need to tab through the task switcher.
  225.                    SendCustomMessage(hFindWnd,
  226.                              RegisterWindowMessage(TABNEXTTASK_MSG));
  227.                    fEatKeystroke = TRUE;
  228.                 }
  229.             }
  230.             else
  231.             {
  232.                 // We did something besides Alt+Tab so reset Alt+Tab mechanism.
  233.                 // This is required because Alt+Tab can perform two functions.
  234.                 // It can bring up the task switcher and it can tab through the
  235.                 // tasks in the task switcher. RanOnce determines the correct
  236.                 // mode of operation.
  237.                 RanOnce = FALSE;
  238.  
  239.                 // Alt+Esc ------------------------------
  240.                 if((pInfoLowLevelEvent->vkCode==VK_ESCAPE)&&
  241.                    ((pInfoLowLevelEvent->flags&LLKHF_ALTDOWN)!=0))
  242.                 {
  243.                     SendCustomMessage(hFindWnd,
  244.                               RegisterWindowMessage(ALT_ESC_MSG));
  245.                     fEatKeystroke = TRUE;
  246.                 }
  247.                 // Ctrl+Esc ------------------------------
  248.                 else if((pInfoLowLevelEvent->vkCode==VK_ESCAPE)&&
  249.                         ((GetKeyState(VK_CONTROL) & 0x8000) != 0))
  250.                 {
  251.                     // Ctrl+Esc does not work on NT4, just 2000
  252.                     if(MajorVersion >= 5)
  253.                     {
  254.                         SendCustomMessage(hFindWnd,
  255.                                   RegisterWindowMessage(CTRL_ESC_MSG));
  256.                         fEatKeystroke = TRUE;
  257.                     }
  258.                 }
  259.  
  260.             } // end else
  261.        
  262.         }  // end switch wParam
  263.  
  264.     }  // end if nCode == HC_ACTION && ScrollLocked
  265.  
  266.     // Call the next hook or eat the key.
  267.     if(fEatKeystroke)
  268.     {
  269.         return 1;
  270.     }
  271.     else
  272.     {
  273.         return CallNextHookEx(CurrentHook, nCode, wParam, lParam);
  274.     }
  275. }
  276. /* -----------------------------------------------------------------------------
  277. Routine:    "SendCustomMessage"
  278.  
  279. Purpose:    Sends the custom message to the window.
  280.  
  281. Parameter            Type               Description
  282. ---------            ----               -----------
  283. hWnd                 HWND               Handle to our window that will receive the
  284.                                         message.
  285. MessageId            UINT               Custom messages
  286.  
  287. Returns              Type               Description
  288. ---------            ----               -----------
  289. NONE
  290.  
  291. Creation Date: July 2000, E. Feldl
  292. ----------------------------------------------------------------------------- */
  293. void PreSysWndProcKeyHook::SendCustomMessage(HWND hWnd, UINT MessageId)
  294. {
  295.     ASSERT(MessageId != 0);
  296.  
  297.     BOOL Status = PostMessage(hWnd, MessageId, NULL, NULL);
  298.  
  299.     ASSERT(Status == TRUE);
  300. }
  301. /* -----------------------------------------------------------------------------
  302. Routine:    "GetServicePack"
  303.  
  304. Purpose:    Gets the NT Service Pack number.
  305.  
  306. Parameter            Type               Description
  307. ---------            ----               -----------
  308. NONE
  309.  
  310. Returns              Type               Description
  311. ---------            ----               -----------
  312. iRet                 int                The Service Pack number
  313.  
  314. Creation Date: July 2000, E. Feldl, M. Vanloon
  315. ----------------------------------------------------------------------------- */
  316. int PreSysWndProcKeyHook::GetServicePack()
  317. {
  318.     OSVERSIONINFO os;
  319.     int iRet=0;
  320.  
  321.     os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  322.     GetVersionEx(&os);
  323.  
  324.     if (os.dwPlatformId == VER_PLATFORM_WIN32_NT)
  325.     {
  326.         if (os.szCSDVersion)
  327.         {
  328.             int pos = strcspn(os.szCSDVersion,"1234567890");
  329.             iRet = atoi(os.szCSDVersion + pos);
  330.         }
  331.     }
  332.  
  333.     return iRet;
  334. }
  335.  
  336. // End of File: LowLevelKeyHook.cpp -----------------------------------------------
Add Comment
Please, Sign In to add comment