🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

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

Re: Still struggling with a DLL for keyboard hooking

#2247
From: Remy Lebeau (TeamB)
Date: Thu, 15 Mar 2007 22:51
280 lines
8029 bytes
"Vladimir Stefanovic" <antivari@sbb.co.yu> wrote in message
news:45f9a429$1@newsgroups.borland.com...

> The code itself works fine for my app. Unfortunately (sometimes)
> it harms other applications causing them to crash, with bunch of
> Illegal operations.

Your hook code is not checking for errors that could escape into the
calling application.  You need to keep hooks as simple and as solid as
possible for exactly the reason of effecting other people's programs.
That is why global hooks are generally frowned on.

> There are two scenarios of harming other apps:
>
> 1. When the DLL is made by "DLL Wizzard" with
> *checked* VCL support. It's size is 12800 bytes then.

I strongly recommend NOT using the VCL in hook DLLs at all.  Too much
overhead that gets injected into every other process.  Personally, I
strive to never use the VCL in any DLL at all, but that is just me

Try this code:

    --- MyHookDll.h ---

    #ifndef MyHookDllH
    #define MyHookDllH

    #ifdef BUILDING_DLL
    #define MYHOOKAPI __declspec(dllexport)
    #else
    #define MYHOOKAPI __declspec(dllimport)
    #endif

    #ifdef __cplusplus
    extern "C" {
    #endif

    MYHOOKAPI BOOL __stdcall SetHook(HWND);
    MYHOOKAPI BOOL __stdcall RemoveHook(void);
    MYHOOKAPI LRESULT CALLBACK CheckKey(int, WPARAM, LPARAM);
    MYHOOKAPI UINT __stdcall GetHookMsg(void);

    #ifdef __cplusplus
    }
    #endif

    #endif


    --- MyHookDll.cpp ---

    #include <windows.h>
    #pragma hdrstop

    #define BUILDING_DLL
    #include "MyHookDll.h"

    typedef struct
    {
        HHOOK ghhookKB;
        HWND hAppWnd;
    } HOOKINFO, *PHOOKINFO;

    HANDLE hFileMapping = NULL;
    PHOOKINFO pHookInfo = NULL;
    HINSTANCE ghInst = NULL;
    bool gbIsWritable = false;
    UINT uiKeyHookMsg = 0;

    int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason,
void *lpReserved)
    {
        switch( reason )
        {
            case DLL_PROCESS_ATTACH:
            {
                ghInst = hinst;

                TCHAR buffer[MAX_PATH+1] = {0};
                ::GetModuleFileName(NULL, buffer, MAX_PATH);

                LPTSTR ptr = buffer;
                LPTSTR filename = buffer;

                while( *ptr != 0 )
                {
                    if( *ptr == TEXT('\\') )
                    {
                        filename = ::CharNext(ptr);
                        ptr = filename;
                    }
                    else
                        ptr = ::CharNext(ptr);
                }

                uiKeyHookMsg =
::RegisterWindowMessage(TEXT("DiKeyHookMsg"));
                if( uiKeyHookMsg )
                {
                    gbIsWritable = (lstrcmpi(filename, TEXT("di.exe"))
== 0);

                    hFileMapping = ::CreateFileMapping(
                        INVALID_HANDLE_VALUE,
                        NULL,
                        gbIsWritable ? PAGE_READWRITE : PAGE_READONLY,
                        0,
                        sizeof(HOOKINFO),
                        TEXT("DiHook"));

                    if( hFileMapping )
                    {
                        pHookInfo = (PHOOKINFO) ::MapViewOfFile(
                            hFileMapping,
                            gbIsWritable ? FILE_MAP_WRITE :
FILE_MAP_READ,
                            0, 0, 0);

                        if( pHookInfo )
                            break;

                        ::CloseHandle(hFileMapping);
                        hFileMapping = NULL;
                    }
                }

                return FALSE;
            }

            case DLL_PROCESS_DETACH:
            {
                RemoveHook();

                if( pHookInfo )
                {
                    ::UnmapViewOfFile(pHookInfo);
                    pHookInfo = NULL;
                }

                if( hFileMapping )
                {
                    ::CloseHandle(hFileMapping);
                    hFileMapping = NULL;
                }

                break;
            }
        }

        return TRUE;
    }

    BOOL __stdcall SetHook(HWND hWnd)
    {
        if( (pHookInfo) && (gbIsWritable) )
        {
            pHookInfo->hAppWnd = hWnd;

            if( pHookInfo->ghhookKB == NULL )
                pHookInfo->ghhookKB = ::SetWindowsHookEx(WH_KEYBOARD,
(HOOKPROC)&CheckKey, ghInst, 0);

            if( pHookInfo->ghhookKB )
                return TRUE;
        }

        return FALSE;
    }

    BOOL __stdcall RemoveHook(void)
    {
        if( (pHookInfo) && (gbIsWritable) )
        {
            pHookInfo->hAppWnd = NULL;

            if( pHookInfo->ghhookKB )
            {
                ::UnhookWindowsHookEx(pHookInfo->ghhookKB);
                pHookInfo->ghhookKB = NULL;
            }

            return TRUE;
        }

        return FALSE;
    }

    LRESULT CALLBACK CheckKey(int nCode, WPARAM wParam, LPARAM lParam)
    {
        LRESULT res = 0;

        if( pHookInfo )
        {
            try
            {
                if( (nCode >= 0)
                    && (nCode != HC_NOREMOVE)
                    && ((lParam & 0x0000FFFF) == 0) // Skip if it's a
repeat
                    && (lParam & 0x20000000)) // Check if Alt is
pressed
                {
                    if( pHookInfo->hAppWnd ) // Skip if no App window
                    {
                        // Send key information to the App window
                        ::SendMessage(pHookInfo->hAppWnd,
uiKeyHookMsg, 0, lParam);
                    }
                }

                res = ::CallNextHookEx(pHookInfo->ghhookKB, nCode,
wParam, lParam);
            }
            catch(...)
            {
            }
        }

        return res;
    }

    UINT __stdcall GetHookMsg(void)
    {
        return uiKeyHookMsg;
    }


    --- Unit1.cpp ---

    #include "MyHookDll.h"
    UINT uiKeyHookMsg = 0;

    __fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
    {
        uiKeyHookMsg = GetHookMsg();
    }

    void __fastcall TForm1::CreateWnd()
    {
        TForm::CreateWnd();
        if( HandleAllocated() )
            SetHook(Handle);
    }

    void __fastcall TForm1::DestroyWnd()
    {
        RemoveHook();
        TForm::DestroyWnd();
    }

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
        SetHook(Handle);
    }

    void __fastcall TForm1::Button2Click(TObject *Sender)
    {
        RemoveHook();
    }

    void __fastcall TForm1::WndProc(TMessage &Message)
    {
        if( (Message.Msg == uiKeyHookMsg) && (uiKeyHookMsg != 0) )
        {
            char Key[80] = {0};
            if( GetKeyNameText(Message.LParam, Key, 80) )
            {
                if( StrComp(Key, "F12") == 0 )
                    ShowMessage("F12");
            }
        }
        else
            TForm::WndProc(Message);
    }


Gambit
Technical Details
Message-ID: <45f9c0a3@newsgroups.borland.com>
Path: arc1-ca.pugleaf.net!g2news1.google.com!news4.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail
References: <45f9a429$1@newsgroups.borland.com>

Show Full Headers
Complete Article Headers
X-Google-Thread: 10cc67,2dee6d400474aadb
X-Google-Attributes: gid10cc67,public
X-Google-Language: ENGLISH,ASCII-7-bit
From: "Remy Lebeau \(TeamB\)" <no.spam@no.spam.com>
Newsgroups: borland.public.cppbuilder.nativeapi
References: <45f9a429$1@newsgroups.borland.com>
Subject: Re: Still struggling with a DLL for keyboard hooking
Date: Thu, 15 Mar 2007 14:51:32 -0800
Lines: 282
X-Priority: 3
X-MSMail-Priority: Normal
X-Newsreader: Microsoft Outlook Express 6.00.2800.1409
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1409
NNTP-Posting-Host: 75.83.34.171
Message-ID: <45f9c0a3@newsgroups.borland.com>
X-Trace: newsgroups.borland.com 1173995683 75.83.34.171 (15 Mar 2007 14:54:43 -0800)
Path: arc1-ca.pugleaf.net!g2news1.google.com!news4.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail