🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.cppbuilder.nativeapi
Article #344

Moving hooke callback to thread - suggestions? (was:Hooks, once again)

#344
From: Anders Johansen
Date: Wed, 07 May 2008 09:40
188 lines
6807 bytes
Hi all,

The code below has a potential flaw: The callback code is 
running in the main thread, and so may block the system event
processing or at least delay it.

Is there an easy/obvious/recommended way to do this? A 
suggestion that has one of the listed attibutes is fine, but 
I would of course love one that has all three :)

Anders

"Anders Johansen" <home@dduck.dk> wrote:
>
>Hi all.
>
>I have so far been using the "old fashioned" approach to 
>keyboard and mouse hooking, meaning putting the hook procedures
>in a DLL, and using the SetWindowsHookEx with WH_KEYBOARD and 
>WH_MOUSE. Now Vista arrives, and this approach is apparently 
>blocked for some applications (notable IE) when not running as 
>Administrator. I understand the rationale is that this allows 
>for code injection, which I guess is fair enough.
>
>This is my alternate approach, submitted for comments and 
>inspiration.
>
>I understand that the _LL versions of the hooks will work. They 
>have the disadvantage of not being available on systems older 
>than NT4 SP3. On the other hand, the callback does not have to 
>be in a DLL, which seems to work - can anybody confirm that this 
>is correct, e.g. that a DLL is NOT needed when using the _LL 
>hooks?
>
>If, as my testing seems to validate, the hooking does not have 
>to happen in a DLL, this allows for a much nicer implementation 
>than the usual approach. Here's my first attempt, in case 
>anybody wants to comment or inspect...
>
>Header:
>#ifndef HookMasterH
>#define HookMasterH
>//---------------------------------------------------------------------------
>
>#include <windows.h>
>#include <map>
>#include <set>
>
>class HookObserver {
>  public:
>    virtual void keyDown(const UINT vkey, const bool altDown, const int keyDownNumber) = 0;
>};
>
>/*
>The HookMaster uses hooks to monitor keyboard and mouse, and MSAA to
>monitor focus change and window move/resize.
>*/
>class HookMaster {
>  private:
>    static HHOOK LLKeyHook;
>    static HHOOK LLMouseHook;
>    static int keyDownNumber;
>    static std::set<HookObserver*> observers;
>
>    static LRESULT CALLBACK LLKeyHookProc(int nCode, WPARAM wParam, LPARAM lParam);
>    static LRESULT CALLBACK LLMouseHookProc(int nCode, WPARAM wParam, LPARAM lParam);
>    static void notifyKeyDown(const UINT vkey, const bool altDown);
>  public:
>    static void addObserver(HookObserver *o);
>    static void removeObserver(HookObserver *o);
>    static int getKeyDownNumber();
>    static bool setHooks();
>    static bool removeHooks();
>};
>
>
>CPP file:
>//---------------------------------------------------------------------------
>
>
>#pragma hdrstop
>
>#include "HookMaster.h"
>#include <SysInit.hpp>
>//---------------------------------------------------------------------------
>
>#pragma package(smart_init)
>
>
>HHOOK HookMaster::LLKeyHook = NULL;
>HHOOK HookMaster::LLMouseHook = NULL;
>int HookMaster::keyDownNumber = 0;
>std::set<HookObserver*> HookMaster::observers;
>
>LRESULT CALLBACK HookMaster::LLKeyHookProc(int nCode, WPARAM wParam, LPARAM lParam) {
>  try {
>    if (nCode<0 || nCode==HC_NOREMOVE )
>        return CallNextHookEx(LLKeyHook, nCode, wParam, lParam);
>    KBDLLHOOKSTRUCT * pData = ( KBDLLHOOKSTRUCT *) lParam;
>    bool Down = (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN);
>    bool Alt=(pData->flags & LLKHF_ALTDOWN); // Alt is down
>    UINT vkey = pData->vkCode;
>    if (Down) {
>      if (GetKeyState(VK_CONTROL)>=0 ) {
>        notifyKeyDown(vkey, Alt);
>      }
>    }
>  } catch (...) {
>  }
>  return CallNextHookEx(LLKeyHook, nCode, wParam, lParam);
>}
>
>LRESULT CALLBACK HookMaster::LLMouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) {
>  try {
>    if (nCode==HC_ACTION) {
>      switch (wParam) {
>        case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
>          notifyKeyDown(VK_RBUTTON, false);
>          break;
>        case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
>          notifyKeyDown(VK_LBUTTON, false);
>          break;
>        case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK:
>          notifyKeyDown(VK_MBUTTON, false);
>          break;
>      }
>    }
>  } catch (...) {
>  }
>  return CallNextHookEx(LLMouseHook, nCode, wParam, lParam);
>}
>
>void HookMaster::addObserver(HookObserver *o) {
>  observers.insert(o);
>}
>
>void HookMaster::removeObserver(HookObserver *o) {
>  observers.erase(o);
>}
>
>int HookMaster::getKeyDownNumber() {
>  return keyDownNumber;
>}
>
>bool HookMaster::setHooks() {
>  if (LLKeyHook == NULL) {
>    LLKeyHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)LLKeyHookProc, HInstance, 0);
>  }
>  if (LLMouseHook == NULL) {
>    LLMouseHook = SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)LLMouseHookProc, HInstance, 0);
>  }
>  return (LLKeyHook != NULL && LLMouseHook != NULL);
>}
>
>bool HookMaster::removeHooks() {
>  if (LLKeyHook != NULL) {
>    if (UnhookWindowsHookEx(LLKeyHook)) {
>      LLKeyHook = NULL;
>    }
>  }
>  if (LLMouseHook != NULL) {
>    if (UnhookWindowsHookEx(LLMouseHook)) {
>      LLMouseHook = NULL;
>    }
>  }
>  return (LLKeyHook == NULL && LLMouseHook == NULL);
>}
>
>
>void HookMaster::notifyKeyDown(const UINT vkey, const bool altDown) {
>  for (std::set<HookObserver*>::iterator i = observers.begin(); i != observers.end(); ++i) {
>    try {
>      HookObserver *obs = *i;
>      obs->keyDown(vkey, altDown, keyDownNumber);
>    } catch (...) {
>      // Something bad happened with the observer
>    }
>  }
>  ++keyDownNumber;
>}
>
>
>Yes, it needs a little clean-up in sethooks, as it may return 
>false and leave a keyboard hook dangling if setting the mouse 
>hook fails...
>
>A
Technical Details
Message-ID: <48217905$1@newsgroups.borland.com>
Path: arc1-ca.pugleaf.net!g2news2.google.com!news1.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!nx01.iad01.newshosting.com!newshosting.com!198.186.194.250.MISMATCH!news-out.readnews.com!news-xxxfer.readnews.com!70.47.10.52.MISMATCH!newspeer1.nac.net!newsfeeds.ihug.co.nz!ihug.co.nz!newsgroups.borland.com!not-for-mail
References: <47c935cb$1@newsgroups.borland.com>

Show Full Headers
Complete Article Headers
X-Google-Thread: 10cc67,4ebd883022a89a5d
X-Google-Attributes: gid10cc67,domainid0,public,usenet
X-Google-Language: ENGLISH,ASCII-7-bit
From: "Anders Johansen" <home@dduck.dk>
Sender: "Anders Johansen" <home@dduck.dk>
Reply-To: "Anders Johansen" <home@dduck.dk>
Subject: Moving hooke callback to thread - suggestions? (was:Hooks, once again)
Newsgroups: borland.public.cppbuilder.nativeapi
X-User-Info: 130.226.221.25     
References:  <47c935cb$1@newsgroups.borland.com>
NNTP-Posting-Host: 207.105.83.66
Message-ID: <48217905$1@newsgroups.borland.com>
Date: 7 May 2008 02:40:21 -0700
X-Trace: newsgroups.borland.com 1210153221 207.105.83.66 (7 May 2008 02:40:21 -0700)
Lines: 189
Path: arc1-ca.pugleaf.net!g2news2.google.com!news1.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!nx01.iad01.newshosting.com!newshosting.com!198.186.194.250.MISMATCH!news-out.readnews.com!news-xxxfer.readnews.com!70.47.10.52.MISMATCH!newspeer1.nac.net!newsfeeds.ihug.co.nz!ihug.co.nz!newsgroups.borland.com!not-for-mail