• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • 在VC++ 6.0下應用Win32系統鉤子技術

    發表于:2007-07-14來源:作者:點擊數: 標簽:
    信息產業部電子第二十二研究所 郎銳 一、引言 鉤子的本質是一段用以處理系統消息的程序,通過系統調用,把它掛入系統。鉤子的種類很多,每種鉤子可以截獲并處理相應的消息,每當特定的消息發出,在到達目的窗口之前,鉤子程序先行截獲該消息、得到對此消息的
    信息產業部電子第二十二研究所 郎銳

    一、引言
    鉤子的本質是一段用以處理系統消息的程序,通過系統調用,把它掛入系統。鉤子的種類很多,每種鉤子可以截獲并處理相應的消息,每當特定的消息發出,在到達目的窗口之前,鉤子程序先行截獲該消息、得到對此消息的控制權。此時鉤子函數可以對截獲的消息進行加工處理,甚至可以強制結束消息的傳遞。這有點類似與MFC中的PreTranslateMessage函數,所不同的是該函數只能用于攔截本進程中的消息,而對系統消息則無能為力。
    二、Win32系統鉤子的實現
    每種類型的鉤子均由系統來維護一個鉤子鏈,最近安裝的鉤子位于鏈的開始,擁有最高的優先級,而最先安裝的鉤子則處在鏈的末尾。要實現Win32的系統鉤子,首先要調用SDK中的API函數SetWindowsHookEx來安裝這個鉤子函數,其原型是:
    HHOOK SetWindowsHookEx(int idHook,
    HOOKPROC lpfn,
    HINSTANCE hMod,
    DWORD dwThreadId);
    其中,第一個參數是鉤子的類型,常用的有WH_MOUSE、WH_KEYBOARD、WH_GETMESSAGE等;第二個參數是鉤子函數的地址,當鉤子鉤到任何消息后便調用這個函數;第三個參數是鉤子函數所在模塊的句柄;第四個參數是鉤子相關函數的ID用以指定想讓鉤子去鉤哪個線程,為0時則攔截整個系統的消息此時為全局鉤子。如果指定確定的線程,即為線程專用鉤子。
    全局鉤子函數必須包含在DLL(動態鏈接庫)中,而線程專用鉤子則可包含在可執行文件中。得到控制權的鉤子函數在處理完消息后,可以調用另外一個SDK中的API函數CallNextHookEx來繼續傳遞該消息。也可以通過直接返回TRUE來丟棄該消息,阻止該消息的傳遞。
    使用全局鉤子函數時需要以DLL為載體,VC6中有三種形式的MFC DLL可供選擇,即Regular statically linked to MFC DLL(標準靜態鏈接MFC DLL)、Regular using the shared MFC DLL(標準動態鏈接MFC DLL)以及Extension MFC DLL(擴展MFC DLL)。第一種DLL在編譯時把使用的MFC代碼鏈接到DLL中,執行程序時不需要其他MFC動態鏈接類庫的支持,但體積較大;第二種DLL在運行時動態鏈接到MFC類庫,因而體積較小,但卻依賴于MFC動態鏈接類庫的支持;這兩種DLL均可被MFC程序和Win32程序使用。第三種DLL的也是動態連接,但做為MFC類庫的擴展,只能被MFC程序使用。
    三、Win32 DLL
    Win32 DLL的入口和出口函數都是DLLMain這同Win16 DLL是有區別的。只要有進程或線程載入和卸載DLL時,都會調用該函數,其原型是:
    BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason, LPVOID lpvReserved);其中,第一個參數表示DLL的實例句柄;第三個參數系統保留;第二個參數指明了當前調用該動態連接庫的狀態,它有四個可能的值:DLL_PROCESS_ATTACH(進程載入)、DLL_THREAD_ATTACH(線程載入)、DLL_THREAD_DETACH(線程卸載)、DLL_PROCESS_DETACH(進程卸載)。在DLLMain函數中可以通過對傳遞進來的這個參數的值進行判別,根據不同的參數值對DLL進行必要的初始化或清理工作。由于在Win32環境下,所有進程的空間都是相互獨立的,這減少了應用程序間的相互影響,但大大增加了編程的難度。當進程在動態加載DLL時,系統自動把DLL地址映射到該進程的私有空間,而且也復制該DLL的全局數據的一份拷貝到該進程空間,每個進程所擁有的相同的DLL的全局數據其值卻并不一定是相同的。當DLL內存被映射到進程空間中,每個進程都有自己的全局內存拷貝,加載DLL的每一個新的進程都重新初始化這一內存區域,也就是說進程不能再共享DLL。因此,在Win32環境下要想在多個進程中共享數據,就必須進行必要的設置。一種方法便是把這些需要共享的數據單獨分離出來,放置在一個獨立的數據段里,并把該段的屬性設置為共享,建立一個內存共享的DLL。

    四、全局共享數據的實現
    可以用#pragma data_seg建立一個新的數據段并定義共享數據,其具體格式為:
    #pragma data_seg ("shareddata")
    HWND sharedwnd=NULL;//共享數據
    #pragma data_seg()
    所有在data_seg pragmas語句之間聲明的變量都將在shareddata段中。僅定義一個數據段還不能達到共享數據的目的,還要告訴編譯器該段的屬性,有兩種方法可以實現該目的(其效果是相同的),一種方法是在.DEF文件中加入如下語句:
    SETCTIONS
    shareddata READ WRITE SHARED
    另一種方法是在項目設置鏈接選項中加入如下語句:
    /SECTION:shareddata,rws
    五、鼠標鉤子程序示例
    本示例程序用到全局鉤子函數,程序分兩部分:可執行程序MouseDemo和動態連接庫MouseHook。首先編制MFC擴展動態連接庫MouseHook.dll:
    (一)選擇MFC AppWizard(DLL)創建項目Mousehook;
    (二)選擇MFC Extension DLL(MFC擴展DLL)類型;
    (三)通過Project菜單的AddToProject子菜單的"New…"添加頭文件MouseHook.h。
    (四)在頭文件中建立鉤子類:
      class AFX_EXT_CLASS CMouseHook:public CObject
      {
      public:
      CMouseHook();  //鉤子類的構造函數
      ~CMouseHook();  //鉤子類的析構函數
      BOOL StartHook(HWND hWnd);   //安裝鉤子函數
      BOOL StopHook();    //卸載鉤子函數
    };
    (五)在MouseHook.cpp文件中加入#include"MouseHook.h"語句;
    (六)加入全局共享數據變量:
      #pragma data_seg("mydata")
      HWND glhPrevTarWnd=NULL;  //上次鼠標所指的窗口句柄
      HWND glhDisplayWnd=NULL;  //顯示目標窗口標題編輯框的句柄
      HHOOK glhHook=NULL;   //安裝的鼠標勾子句柄
      HINSTANCE glhInstance=NULL; //DLL實例句柄
    #pragma data_seg()
    (七)在DEF文件中定義段屬性:
      SECTIONS
      mydata READ WRITE SHARED
    (八)在主文件MouseHook.cpp的DllMain函數中加入保存DLL實例句柄的語句:
    extern "C" int APIENTRY
    DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
    {
    UNREFERENCED_PARAMETER(lpReserved);
    if (dwReason == DLL_PROCESS_ATTACH)
    {
    if (!AfxInitExtensionModule(MouseHookDLL, hInstance))
    return 0;
    new CDynLinkLibrary(MouseHookDLL);
    glhInstance=hInstance;    //插入保存DLL實例句柄
    }
    else if (dwReason == DLL_PROCESS_DETACH)
    {
    AfxTermExtensionModule(MouseHookDLL);
    }
    return 1; // ok
    }
    這個函數最重要的部分是調用AfxInitExtensionModule(),它初始化DLL使它在MFC框架中正確的工作。它需要傳遞給DllMain()的DLL實例句柄和AFX_EXTENSION_MODULE結構,結構中存在著對MFC有用的信息。
    (九) 類CMouseHook的成員函數的具體實現:
    Cmousehook::Cmousehook() //類構造函數
    {
    }
    Cmousehook::~Cmousehook() //類析構函數
    {
      stophook();
    }
    BOOL Cmousehook::starthook(HWND hWnd)  //安裝鉤子并設定接收顯示窗口句柄
    {
    BOOL bResult=FALSE;
    glhHook=SetWindowsHookEx(WH_MOUSE,MouseProc,glhInstance,0);
    if(glhHook!=NULL)
    bResult=TRUE;
    glhDisplayWnd=hWnd;  //設置顯示目標窗口標題編輯框的句柄
    return bResult;
    }
    BOOL Cmousehook::stophook()  //卸載鉤子
    {
    BOOL bResult=FALSE;
    if(glhHook)
    {
    bResult= UnhookWindowsHookEx(glhHook);
    if(bResult)
    {
    glhPrevTarWnd=NULL;
    glhDisplayWnd=NULL;//清變量
    glhHook=NULL;
    }
    }
    return bResult;
    }
    (十) 鉤子函數的實現
    LRESULT WINAPI MouseProc(int nCode,WPARAM wparam,LPARAM lparam)
    {
    LPMOUSEHOOKSTRUCT pMouseHook=(MOUSEHOOKSTRUCT FAR *) lparam;
    if (nCode>=0)
    {
    HWND glhTargetWnd=pMouseHook->hwnd;  //取目標窗口句柄
    HWND ParentWnd=glhTargetWnd;
    while (ParentWnd !=NULL)
    {
    glhTargetWnd=ParentWnd;
    ParentWnd=GetParent(glhTargetWnd); //取應用程序主窗口句柄
    }
    if(glhTargetWnd!=glhPrevTarWnd)
    {
    char szCaption[100];
    GetWindowText(glhTargetWnd,szCaption,100); //取目標窗口標題
    if(IsWindow(glhDisplayWnd))
    SendMessage(glhDisplayWnd,WM_SETTEXT,0,(LPARAM)(LPCTSTR)szCaption);
    glhPrevTarWnd=glhTargetWnd;   //保存目標窗口
    }
    }
    return CallNextHookEx(glhHook,nCode,wparam,lparam); //繼續傳遞消息
    }
    編譯完成便可得到運行時所需的鼠標鉤子的動態連接庫MouseHook.dll和鏈接時用到的MouseHook.lib。
    六、集成
    下面新建一調用鼠標鉤子動態連接庫的鉤子可執行程序:
    (一) 用MFC的AppWizard(EXE)創建項目MouseDemo;
    (二) 選擇"基于對話應用",其余幾步均為確??;
    (三) 在對話框上加入一個編輯框IDC_EDIT1;
    (四) 在MouseDemo.h中加入對Mousehook.h的包含語句:#Include"Mousehook.h";
    (五) 在CMouseDemoDlg.h的CMouseDemoDlg類定義中添加私有數據成員:CMouseHook m_hook;
    (六) 在OnInitDialog函數的"TODO注釋"后添加:
    CWnd * pwnd=GetDlgItem(IDC_EDIT1);  //取得編輯框的類指針
    m_hook.StartHook(pwnd->GetSafeHwnd()); //取得編輯框的窗口句柄并安裝鉤子
    (七)鏈接DLL庫,即把Mousehook.lib加入到項目設置鏈接標簽中;
    (八)把MouseHook.h和MouseHook.lib復制到MouseDemo工程目錄中,MouseHook.dll復制到Debug目錄下。編譯執行程序即可。當鼠標滑過窗口時便會在編輯框中將此窗口的標題顯示出來。
    結論:
    系統鉤子具有相當強大的功能,通過這種技術可以對幾乎所有的Windows
    系統消息進行攔截、監視、處理。這種技術可以廣泛應用于各種軟件,尤其是需要
    有監控、自動記錄等對系統進行監測功能的軟件。本程序只對鼠標消息進行攔截,
    相應的也可以在Win32環境下對鍵盤、端口等應用此技術完成特定的功能。


    摘自:計算機世界網

    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>