Article View: borland.public.cppbuilder.nativeapi
Article #2247Re: Still struggling with a DLL for keyboard hooking
From: Remy Lebeau (TeamB)
Date: Thu, 15 Mar 2007 22:51
Date: Thu, 15 Mar 2007 22:51
280 lines
8029 bytes
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-mailReferences:
<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