C++ Builder 5編HOOK程式
一,
HINSTANCE g_hinstDll = NULL;
HHOOK g_hhook = NULL;
HWND g_hwndPost = NULL;
UINT g_uMsgNotify = WM_USER;
HOOKPROC KeyboardHook_HookProc ( int nCode, WPARAM wParam, LPARAM lParam)
{
LRESULT lResult = CallNextHookEx(g_hhook, nCode, wParam, lParam);
if (nCode == HC_ACTION)
{
PostMessage(g_hwndPost, g_uMsgNotify, wParam, lParam);
}
return((HOOKPROC)lResult);
}
///
BOOL WINAPI SetKeyboardHook (HWND hWndPost, UINT Msg)
{
HHOOK hhook;
if (g_hhook != NULL) return(FALSE);
g_hwndPost = hWndPost;
g_uMsgNotify = Msg;
Sleep(0);
if (g_hLogHook==NULL)
hhook = SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyboardHook_HookProc,g_hinstDll, 0);
InterlockedExchange((PLONG) &g_hhook, (LONG) hhook);
return(g_hhook != NULL);
}
///
BOOL WINAPI ReleaseKeyboardHook()
{
BOOL fOK = TRUE;
if (g_hhook != NULL)
{
fOK = UnhookWindowsHookEx(g_hhook);
g_hhook = NULL;
}
return(fOK);
}
BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
g_hinstDll = hinstDll;
break;
}
return(TRUE);
}
二,
在Borland的Community上找到了這篇文章,可以解決這個問題了。如下:
http://community.borland.com/article/0,1410,20008,00.html
///
C++Builder 4.0 is the first C++Builder compiler that supports shared memory segments. This document explains how to use this feature in windows DLL.
To change the data segment and the class name, you need to add #pragma option -zR[SEGMENT NAME] and #pragma option -zT[CLASS NAME] to the file you want the data shared from. Below is the source file I am going to export the integer named 'data':
File: SharedData.cpp
//---------------------------------------------------------------------------
// Borland C++Builder
// Copyright (c) 1987, 1999 Inprise Corporation. All Rights Reserved.
//---------------------------------------------------------------------------
#pragma option -zRSHSEG // change default data segment name
#pragma option -zTSHCLASS // change default data class name
// Here is the initialized data that will be shared.
int data = 0;
Notice that the segment name for this file is: SHSEGSHCLASS. A .def file is required for the linker to create the shared segement. Below is what the .def file looks like:
File: Shared.def
LIBRARY SHAREDDLL
SEGMENTS
SHSEG CLASS 'SHCLASS' SHARED
三
當你的DLL程式被其它各個程式調用時,每調用一次,将産生一個
DLL的執行個體,其實代碼在記憶體中僅有一套,但DLL中的變量即資料段将
産生多個,這若幹個資料段是互不幹擾、是不能共享的,但在一些特
殊情況下,就不能滿足我們的要求了,比如,使用者的全局鈎子程式就
是一個.DLL,這個.DLL會被記憶體所有的程序調用, 如果它的資料段不
能共享,就變成了多個局部鈎子了,好在API已替你想好了一個間接
辦法,你可用一個“共享名”申請一塊共享記憶體塊,進行讀寫:
HANDLE GetShare(char * &ShareP,int size,char *ShareName)
{ ShareP申請的記憶體塊位址,size位元組數,ShareName共享名
HANDLE fh=CreateFileMapping((HANDLE)-1,0,
PAGE_READWRITE,0,
Size,
ShareName);
ShareP=(char *)MapViewOfFile(fh,
FILE_MAP_ALL_ACCESS,
0,0,0);
if (GetLastError()!=ERROR_ALREADY_EXISTS)
ZeroMemory(ShareP,size); // 共享區初始化
return(fh);
}
char * ShareP=NULL;
void test() // 申請一塊128個位元組的字元數組
{
HANDLE fh=GetShare(ShareP,128,"ShareForMyProg");
for (int i=0;i<128;i++)
ShareP[i]=i;
CloseHandle(fh);
}
如果你的多個程式之間或同一個程式多次同時運作,也可借助這個辦法進
變量通訊;
在VC++中,若要為DLL定義一個共享記憶體段更簡單,這是一種直接定義的
辦法:
#pragma data_seg("Shared")
int x,y;
char s[128];
#pragma data_seg
#pragma comment(linker,"/section:Shared,rws")
真簡單,可惜在C++BUILDER5.0中經試驗好象不能接受這種方法;
對于BCB,能不能實作DLL中直接定義共享記憶體塊内,請看下列一段文字:
http://community.borland.com/article/0,1410,20008,00.html
///
C++Builder 4.0 is the first C++Builder compiler that supports shared memory segments.
This document explains how to use this feature in windows DLL.
To change the data segment and the class name, you need to add
#pragma option -zR[SEGMENT NAME] and
#pragma option -zT[CLASS NAME] to the file you want the data shared from.
Below is the source file I am going to export the integer named 'data':
File: SharedData.cpp
//---------------------------------------------------------------------------
// Borland C++Builder
// Copyright (c) 1987, 1999 Inprise Corporation. All Rights Reserved.
//---------------------------------------------------------------------------
#pragma option -zRSHSEG // change default data segment name
#pragma option -zTSHCLASS // change default data class name
// Here is the initialized data that will be shared.
int data = 0;
Notice that the segment name for this file is: SHSEGSHCLASS. A .def file
is required for the linker to create the shared segement. Below is what the
.def file looks like:
File: Shared.def
LIBRARY SHAREDDLL
SEGMENTS
SHSEG CLASS 'SHCLASS' SHARED
可見C++BUILDER4.0與DELPHI已能提供直接實作DLL記憶體段共享問題,請高手邦忙一起
試一試:在BCB或DELPHI具體應怎樣做?
四
// 下面的程式将産生有三個導出函數的MouseHook.DLL
#include <windows.h>
#pragma argsused
typedef // 為共享區定義結構
struct
{
POINT MouseLoc; // 存放滑鼠位置
HHOOK NewHook; // 存放新鈎子句柄
int LoadCount; // DLL裝入次數計數
} TShareMem;
TShareMem *ShareMem=NULL;
HINSTANCE DllHinst;
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
DllHinst=hinst;
static HANDLE fh; // DLL共享區句柄
if (reason==DLL_PROCESS_ATTACH) // DLL入口
{ // 為共享區申請共享單元
fh=CreateFileMapping((HANDLE)-1,0,
PAGE_READWRITE,0,
sizeof(TShareMem),
"ShareForMouseHook");
ShareMem=(TShareMem *)MapViewOfFile(fh,
FILE_MAP_ALL_ACCESS,
0,0,0);
if (GetLastError()!=ERROR_ALREADY_EXISTS)
ZeroMemory(ShareMem,sizeof(TShareMem));
// 共享區初始化
ShareMem->LoadCount+=1; // 裝入計數
}
if (reason==DLL_PROCESS_DETACH) // DLL出口處理
{
ShareMem->LoadCount-=1;
CloseHandle(fh);
}
return 1;
}
extern "C" __declspec(dllexport)
void GetMouse(int &mx,int &my,int &loadcount) // DLL導出函數GetMouse()
{
if (ShareMem!=NULL)
{
mx=ShareMem->MouseLoc.x;
my=ShareMem->MouseLoc.y;
loadcount=ShareMem->LoadCount;
}
}
LRESULT CALLBACK MouseHook(int nCode,
WPARAM wParam,LPARAM lParam)
{
if (nCode==HC_ACTION)
{
MOUSEHOOKSTRUCT *l=(MOUSEHOOKSTRUCT *)lParam;
ShareMem->MouseLoc=l->pt; //送滑鼠位置
}
return(CallNextHookEx(ShareMem->NewHook,nCode,wParam,lParam));
}
extern "C" __declspec(dllexport)
void EnableHook() // 導出函數EnableHook()
{
if (ShareMem!=NULL)
if (ShareMem->NewHook==NULL) // 安裝新鈎子
ShareMem->NewHook=SetWindowsHookEx(WH_MOUSE,
(HOOKPROC)MouseHook,
DllHinst,0);
}
extern "C" __declspec(dllexport)
void DisableHook() // 導出函數DisableHook()
{
if (ShareMem!=NULL)
if (ShareMem->NewHook!=NULL)
{
UnhookWindowsHookEx(ShareMem->NewHook);
ShareMem->NewHook=NULL; // 卸掉新鈎子
}
}
//=======================================================================
#include <vcl.h>
#pragma hdrstop
#include "CallUnit1.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
extern "C" __declspec(dllimport)
void EnableHook(); // DLL導入函數1
extern "C" __declspec(dllimport)
void DisableHook(); // DLL導入函數2
extern "C" __declspec(dllimport)
void GetMouse(int &mx,int &my,int &loadcount); // DLL導入函數3
void __fastcall TForm1::Button1Click(TObject *Sender)
{
EnableHook();
int x,y,loadcount;
while (!Application->Terminated)
{ // 不停在從DLL中取回滑鼠位置
GetMouse(x,y,loadcount);
Edit1->Text=String(x)+","+String(y)+":"+String(loadcount);
Application->ProcessMessages();
}
}
void __fastcall TForm1::Button2Click(TObject *Sender)
{
DisableHook();
}
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
DisableHook();
}
//---------------------------------------------------------------------------
五
步驟如下:
在DLL中的工程中,假設為MouseHook.bpr(産生MouseHook.DLL)
1.在Unit1.cpp的最前面(#include <windows.h>之前)加上
#pragma option -zRSHSEG // 改變預設資料段名
#pragma option -zTSHCLASS // 改變預設資料類名
2.建立一工程同名的純文字檔案MouseHook.def,其内容隻要
一行:
SEGMENTS SHSEG CLASS 'SHCLASS' SHARED
并将此檔案用Project->Add Project增加到工程中;
3.在你的程式代碼的前面定義的全局變量都将是DLL共享的,
在Unit1.cpp中,例如:
// 下面的程式将産生有三個導出函數的MouseHook.DLL
// 純文字檔案 MouseHook.def的内容如下:
// SEGMENTS SHSEG CLASS 'SHCLASS' SHARED
#pragma option -zRSHSEG // 改變預設資料段名
#pragma option -zTSHCLASS // 改變預設資料類名
#include <windows.h>
#pragma argsused
// 以下都将是共享區記憶體變量
POINT MouseLoc={0,0}; // 存放滑鼠位置
HHOOK NewHook=NULL; // 存放新鈎子句柄
int LoadCount=0; // DLL裝入次數計數
HINSTANCE DllHinst;
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
DllHinst=hinst;
if (reason==DLL_PROCESS_ATTACH) // DLL入口
LoadCount+=1; // 裝入計數
else
if (reason==DLL_PROCESS_DETACH) // DLL出口處理
LoadCount-=1;
return 1;
}
extern "C" __declspec(dllexport)
void GetMouse(int &mx,int &my,int &js) // DLL導出函數GetMouse()
{
mx=MouseLoc.x; // 送出滑鼠位置
my=MouseLoc.y;
js=LoadCount; // 送出DLL裝入次數
}
LRESULT CALLBACK MouseHook(int nCode,
WPARAM wParam,LPARAM lParam)
{
if (nCode==HC_ACTION)
{
MOUSEHOOKSTRUCT *l=(MOUSEHOOKSTRUCT *)lParam;
MouseLoc=l->pt; //送滑鼠位置
}
return(CallNextHookEx(NewHook,nCode,wParam,lParam));
}
extern "C" __declspec(dllexport)
void EnableHook() // 導出函數EnableHook()
{
if (NewHook==NULL) // 安裝新鈎子
NewHook=SetWindowsHookEx(WH_MOUSE,
(HOOKPROC)MouseHook,
DllHinst,0);
}
extern "C" __declspec(dllexport)
void DisableHook() // 導出函數DisableHook()
{
if (NewHook!=NULL)
{
UnhookWindowsHookEx(NewHook);
NewHook=NULL; // 卸掉新鈎子
}
}
//==========================================================
// CallHook.EXE,将調用全局滑鼠全局鈎子MouseHook.DLL
// 靜态裝入MouseHook.DLL,工程中須用 MouseGook.Lib
#include <vcl.h>
#pragma hdrstop
#include "CallUnit1.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
extern "C" __declspec(dllimport)
void EnableHook(); // DLL導入函數1
extern "C" __declspec(dllimport)
void DisableHook(); // DLL導入函數2
extern "C" __declspec(dllimport)
void GetMouse(int &mx,int &my,int &loadcount); // DLL導入函數3
void __fastcall TForm1::Button1Click(TObject *Sender)
{
EnableHook();
int x,y,loadcount;
while (!Application->Terminated)
{ // 不停在從DLL中取回滑鼠位置
GetMouse(x,y,loadcount);
Edit1->Text=String(x)+","+String(y);
Edit2->Text=loadcount; // 顯示DLL裝入次數
Application->ProcessMessages();
}
}
void __fastcall TForm1::Button2Click(TObject *Sender)
{
DisableHook();
}
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
DisableHook();
}
// ok,已經深夜1點了,别忘了給俺加點分!!!!!!!!!!!!!!!!
六
VC的程式
#include <windows.h>
#include <windowsx.h>
#include <tchar.h>
HINSTANCE g_hinstDll = NULL;
#pragma data_seg(".drectve")
static char szLinkDirectiveShared[] = "-section:Shared,rws";
#pragma data_seg()
#pragma data_seg("Shared")
HHOOK g_hhook = NULL;
HWND g_hwndPost = NULL;
UINT g_uMsgNotify = WM_USER;
#pragma data_seg()
static LRESULT WINAPI KeyboardHook_HookProc (
int nCode,
WPARAM wParam,
LPARAM lParam)
{
LRESULT lResult = CallNextHookEx(g_hhook, nCode, wParam, lParam);
if (nCode == HC_ACTION)
{
PostMessage(g_hwndPost, g_uMsgNotify, wParam, lParam);
}
return(lResult);
}
BOOL WINAPI SetKeyboardHook (HWND hWndPost, UINT Msg)
{
HHOOK hhook;
if (g_hhook != NULL) return(FALSE);
g_hwndPost = hWndPost;
g_uMsgNotify = Msg;
Sleep(0);
hhook = SetWindowsHookEx(WH_KEYBOARD, KeyboardHook_HookProc, g_hinstDll, 0);
InterlockedExchange((PLONG) &g_hhook, (LONG) hhook);
return(g_hhook != NULL);
}
BOOL WINAPI ReleaseKeyboardHook()
{
BOOL fOK = TRUE;
if (g_hhook != NULL)
{
fOK = UnhookWindowsHookEx(g_hhook);
g_hhook = NULL;
}
return(fOK);
}
BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
g_hinstDll = hinstDll;
break;
}
return(TRUE);
}