Keyb Hooks LIST

How can I retrieve a list of keyboard hooks
installed and the respective applications who
called them ?
LVL 3
bryan7Asked:
Who is Participating?
 
Lee_NoverConnect With a Mentor Commented:
here's the complete project code
haven't tested it, just compiled it successfully :)
it was a minor change to one of my other hooks so it should work
I'm not shure about the TList being stored in the mmf
if that doesn't work then simply make a static array of cardinal or some record
---------------------------------------------------------

library lnKbdDebugHook;

uses
  Windows, Classes;

{$R *.RES}


const
    WM_USER = $0400;
    WM_lnHOOK = WM_USER + 133;

    errSuccess  = 1;
    errHooked   = 0;
    errUnhooked = 0;
    errCantHook = -1;
    errCantUnHk = -1;

type
  PHookRec = ^THookRec;
  THookRec = packed record
    MainWindow: HWND;
    HookID: HHOOK;
    HookList: TList;
  end;


var
   HookRec: PHookRec = nil;
   hMapObject: THandle = 0;


// hook procedure
function hpWSH(nCode: integer; wParam: WPARAM; lParam: LPARAM): LRESULT;stdcall;
var lpDHI: PDebugHookInfo;
    I: Integer;
    found: boolean;
begin
     try
        // check if it's a keybd hook and if we should process the message
        if (wParam = WH_KEYBOARD) and (nCode = HC_ACTION) then begin
           lpDHI:=PDebugHookInfo(lParam);
           found:=false;
           // check our list if the threadid exists
           with HookRec^.HookList do begin
             for I:=0 to Count-1 do
                 if Cardinal(Items[I]) = lpDHI^.idThreadInstaller then begin
                    found:=true;
                    break;
                 end;
             // if threadid not found add it to the list
             if not found then
                Add(Pointer(lpDHI^.idThreadInstaller));
           end;

           // notify our main window
           if HookRec^.MainWindow > 0 then
              PostMessage(HookRec^.MainWindow, WM_lnHOOK, wParam, lParam);
        end;
     finally
        Result:=CallNextHookEx(HookRec^.HookID, nCode, wParam, lParam);
     end;
end;

// set the notification window
function SetMainWindow(const hWin: hWND): hWND;stdcall;
begin
     HookRec^.MainWindow:=hWin;
     Result:=hWin;
end;

// start hook
function HookWindoze: Integer;stdcall;
begin
     if HookRec^.HookID = 0 then begin
        HookRec^.HookID:=SetWindowsHookEx(WH_DEBUG, hpWSH, hInstance, 0);
        if HookRec^.HookID = 0 then
           Result:=errCantHook
        else
           Result:=errSuccess;
     end else Result:=errHooked;
end;

// stop hook
function UnhookWindoze: Integer;stdcall;
begin
     if HookRec^.HookID <> 0 then begin
        if UnhookWindowsHookEx(HookRec^.HookID) then
           Result:=errSuccess
        else
           Result:=errCantUnHk;
        HookRec^.HookID:=0;
     end else Result:=errUnhooked;
end;

function GetHookCount: Integer; stdcall;
begin
     try
        Result:=HookRec.HookList.Count;
     except
        Result:=-2;
     end;
end;

function GetHookID(Index: Integer): Cardinal; stdcall;
begin
     try
        Result:=Cardinal(HookRec.HookList.Items[Index]);
     except
        Result:=0;
     end;
end;

procedure EntryPointProc(Reason: Integer);
begin
  case Reason of
    DLL_PROCESS_ATTACH:
      begin // reserve 4k for the list (cca 1000 entries)
        hMapObject:=CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, SizeOf(THookRec) + 4069, 'ln_kbdList');
        HookRec:=MapViewOfFile(hMapObject, FILE_MAP_WRITE, 0, 0, 0);
        // check if the list already created
        if not Assigned(HookRec^.HookList) then
           HookRec^.HookList:=TList.Create;
      end;

    DLL_PROCESS_DETACH:
      begin
        try
          // clear the list each time a process detaches
          // we could check the threads ids for their validity, but in order to do that
          // we'd need to have their handles but we only have their IDs
          // on win me/2000/xp there's a function called OpenThread
          // with it we could check if the thread id is still valid
          // no support for that function on win 9x systems
          // this should suffice coz with one key press we get all the installed keybd hooks
          // ofcourse if all of them call CallNextHookEx :)
          HookRec^.HookList.Clear;
        finally
          UnMapViewOfFile(HookRec);
          // close the handle to the map object
          // it will not close the handle while there's at least one open View
          CloseHandle(hMapObject);
        end;
      end;
  end;
end;

// ---------- export funkcije
exports
   SetMainWindow,
   HookWindoze,
   UnhookWindoze,
   GetHookCount,
   GetHookID;


begin
     DllProc := @EntryPointProc;
     EntryPointProc(DLL_PROCESS_ATTACH);
end.


hope it works for you :)
0
 
Lee_NoverCommented:
create a system debug hook with SetWindowsHookEx with WH_DEBUG

in the DebugProc check if it's a keyboard hook
if wParam = WH_DEBUG then begin
...
check the DEBUGHOOKINFO for idThreadInstaller
that's the thread that installed the hook

getting the application of the thread that installed the hook is another thing
it could even be installed from within a thread created in a dll function which was called from some app :)
about getting the list .. simply add a hook each time you get notified of one
ofcourse check if it's in the list already
I'm assuming you know about system hooks so I won't code it for ya now
0
 
Lee_NoverCommented:
if wParam = WH_DEBUG then begin

darn .. that should've been
if wParam = WH_KEYBOARD then begin
...
0
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
bryan7Author Commented:
Hello, thanks for the answer.. however I'm not
that good on hooks ;( I can make a system key hook
in a dll but that's all my knowledge about hooks =(

Can you make the code for me ? I need it to get the list
of all currently set keyboard hooks, I'll add more points
if you wish... I really need this app.

btw, if you know of an already made application that
does that (no need for source) I'll give you the points
too :)

Thanks.
0
 
Lee_NoverCommented:
don't know of such an app
I'll write the code as it's not that much work
when I wake up :)
0
 
bryan7Author Commented:
Hello, thanks for the code, I've been
trying to implement the app to get the
list from the dll with no succes :(
would you mind making it for me ? I
can add more points as wished :)

(you'll get A graded)
0
 
smurffCommented:
listening
0
 
Lee_NoverCommented:
:)
in my spare time ... today/tomorrow
0
 
bryan7Author Commented:
:)
0
 
quantum2Commented:
listening
0
 
Lee_NoverCommented:
sorry I was away for a "few" days ...
have you got it working ? if not I'll make a sample app to show you how to use that dll
0
 
bryan7Author Commented:
haven't got it running yet,
would be nice if you could
make that app :)

thanks.
0
 
Lee_NoverCommented:
ok I will :)
0
 
pnh73Commented:
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

Accept answer from Lee_Nover

Please leave any comments here within the next seven days.
 
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!
 
Paul (pnh73)
EE Cleanup Volunteer
0
 
Lee_NoverCommented:
humz ..
if anybody needs a List that's shared between processes then check out my TGlobalList ;)
http://www.siwww.net/Delphi/GLTest.zip

just change the TGLItem to fit your needs
it must not contain any pointer type fields !
for strings use a fixed length array of char

it already includes locking mechanisms so it's completely thread/process safe ;)
0
All Courses

From novice to tech pro — start learning today.