国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
DLL

下載源代碼 - 22 Kb

 

     對于如何使用和創(chuàng)建鉤子有許多的爭議,這篇文章試圖澄清這些問題。

注意:如果你只是在自己的進(jìn)程內(nèi)使用鉤子則不會有下面的問題, 這只發(fā)生在你使用系統(tǒng)鉤子的時候。

 

    關(guān)鍵問題在于 地址空間,DLL函數(shù)中的代碼所創(chuàng)建的任何對象(包括變量)都?xì)w調(diào)用它的線程或進(jìn)程所有。當(dāng)進(jìn)程在載入DLL時,操作系統(tǒng)自動把DLL地址映射到該進(jìn)程的私有空間,也就是進(jìn)程的虛擬地址空間,而且也復(fù)制該DLL的全局?jǐn)?shù)據(jù)的一份拷貝到該進(jìn)程空間。也就是說每個進(jìn)程所擁有的相同的DLL的全局?jǐn)?shù)據(jù),是私有的,DLL成為進(jìn)程的一部分,以這個進(jìn)程的身份執(zhí)行,使用這個進(jìn)程的堆棧。這意味著數(shù)據(jù)會被重新初始化。典型地,它們將是零。

 

    有人建議在DLL上存放數(shù)據(jù)的地址。 這是不可能的。有人反對? 那好,這不是不可能的,但這是不可能有什么 用途 的。既使你創(chuàng)建的是對DLL 的所有實(shí)例可見的共享內(nèi)存變量,這一變量只有在儲存它的進(jìn)程中才有實(shí)際的意義。 對于所有其它的進(jìn)程,這僅僅是一串比特位,并且如果你設(shè)法使用它作為地址,對于事件被攔截的進(jìn)程而言,這個地址是完全無用甚至導(dǎo)致程序崩潰。

 

    這個分開的地址空間的概念是一個難以掌握的概念。 讓我使用圖片說明它。

 

 

 

     我們這里有三個進(jìn)程。 你的進(jìn)程被顯示在左邊。 DLL 中有代碼,有數(shù)據(jù),并且有一個共享的數(shù)據(jù)段。 現(xiàn)在當(dāng)鉤子DLL 執(zhí)行一次對進(jìn)程A的事件攔截 ,系統(tǒng)自動把DLL地址映射到該進(jìn)程的私有空間,也就是進(jìn)程的虛擬地址空間,而且也復(fù)制該DLL的全局?jǐn)?shù)據(jù)的一份拷貝到該進(jìn)程空間。巧合地話,他們會被遷入到進(jìn)程A 同樣的虛擬地址 進(jìn)程A它自己的私有的拷貝 數(shù)據(jù)段,那么進(jìn)程A "Data"中看見的要么是自己私有的 ,要么是無法影響其他進(jìn)程的(或由其它進(jìn)程影響的!). 這里麻煩的是 共享 數(shù)據(jù)段,(顯示紅色的。)在你的進(jìn)程和進(jìn)程A中指示的是同樣的內(nèi)存頁面。 注意,巧合地話,這些內(nèi)存頁出現(xiàn)在同樣的虛擬地址上。 如果對你的進(jìn)程和進(jìn)程A同時進(jìn)行調(diào)試,并且注意看在共有的數(shù)據(jù)段中的 &something ,同時看看在進(jìn)程中A中同樣的 &something ,你會看到同樣的數(shù)據(jù),甚至于它們是在在同樣的地址。 如果你使用調(diào)試器去改變,或許你會看到程序改變了 &something 的值,你可以轉(zhuǎn)到另一進(jìn)程,檢查它,看看在那里出現(xiàn)的新值。

 

     

      讓我們看一看在進(jìn)程B會發(fā)生什么 。 當(dāng)事件在進(jìn)程中B中被鉤時,DLL 被映射。代碼被遷入到進(jìn)程中B中另外的一個地址。如果你調(diào)試進(jìn)程中B ,留意在共有的區(qū)域中的 &something,你會發(fā)現(xiàn) &something 地址是不同的,但 &something 內(nèi)容會是同樣的; 在你的進(jìn)程中或進(jìn)程A中對&something內(nèi)容做的改變立刻就能在進(jìn)程B中看見,即使進(jìn)程B是在另外的一個地址(虛擬地址)看見的。(這是在同樣的物理內(nèi)存地點(diǎn))。當(dāng)我提到巧合時,"巧合" 是指被策劃; Windows總是試圖將DLL映射入同樣的虛擬地址, 它試圖這么干,但它很少成功。

 

      這就意味著,如果你在DLL中存放了一個指向回調(diào)函數(shù)的指針,但在實(shí)際運(yùn)行進(jìn)程A 或進(jìn)程B時,它可能會指向別的地址。這也意味著你將不能在DLL中使用MFC--它不能是一個擴(kuò)展MFC DLLMFC DLL,因?yàn)檫@些DLL(動態(tài)鏈接庫)會調(diào)用MFC 函數(shù)。

 

     那么MFC 函數(shù)在哪里? 他們是在你的地址空間,不是在進(jìn)程A或進(jìn)程B 地址空間! 因?yàn)樗麄兛赡苁怯?/span>Visual.basic ,Java或其他語言寫的 , 所以你必須寫straight-C DLL ,并且我建議你忽略整個C runtime library.,只使用API 。 lstrcpy 代替 strcpy tcscpy,用 lstrcmp 代替 strcmp tcscmp,等等。

如何讓你的DLL與其controlling server 通信?

      

       一種解答將使用 ::PostMessage ::SendMessage 函數(shù)。(我這里提到的是原始API 的調(diào)用,不是MFC 的調(diào)用!) 每當(dāng)可能使用 ::PostMessage,盡可能使用它優(yōu)先于使用 ::SendMessage。否則,如果你的進(jìn)程不幸停止,因?yàn)榇蠹叶急蛔钄r在一個永遠(yuǎn)不會返回的::SendMessage,其他進(jìn)程也將停止,然后是整個系統(tǒng)都停止。

 

       你也可以考慮在共享內(nèi)存區(qū)域使用信息隊列,但那個題目在這篇文章范圍之外。

::SendMessage ::PostMessage中,你無法傳回一個指針 (我們將忽略傳回一個相對指針進(jìn)入共享內(nèi)存區(qū)域的問題; 那也是在這篇文章范圍之外). 這是因?yàn)槟隳苁褂玫娜我恢羔樦甘镜牡刂芬词窃?/span>DLL 中, 要么是在在被鉤的進(jìn)程中。(進(jìn)程A 或進(jìn)程B) 因此在你的進(jìn)程中,這個指針是完全無用的。 你只能通過在 WPARAM LPARAM中的信息傳回地址空間。

 

       I 我強(qiáng)烈 建議為此使用登記的窗口消息。 你能發(fā)送消息到 MESSAGE_MAP(消息映射) 窗口,并在此使用 ON_REGISTERED_MESSAGE 宏指令。

 

     現(xiàn)在關(guān)鍵是要得到 那個窗口的HWND(句柄) 幸運(yùn)的是,這很容易。

 

你必須做的第一件事是創(chuàng)建共有的數(shù)據(jù)段。 所以我們使用 # pragma data_seg 聲明。 使用某一好記的數(shù)據(jù)段名字(它必須是沒有比8 個字符長) 。我想強(qiáng)調(diào)名字是任意的,這里使用了我自己的名字。 我發(fā)現(xiàn)如果我使用好的名字象 .SHARE .SHR .SHRDATA,別人會認(rèn)為名字有特殊的意義。 但是,我要說NO。

 

# pragma data_seg(".JOE")

HANDLE hWnd = NULL;

# pragma dta_seg()

# pragma comment(linker ,"/ section:.JOE,rws ")

 

    # pragma 聲明一個數(shù)據(jù)段,在此范圍內(nèi)聲明的變量在初始化后將被指派到該數(shù)據(jù)段, 假設(shè)他們初始化. 如未初始化,變量將被分配到缺省數(shù)據(jù)段,而# pragma  不起作用。

 

      初看起來, 這將阻止你在共有的數(shù)據(jù)段使用一些C++ 對象,因?yàn)槟銦o法初始化C++中用戶定義的對象。 這看來是一個根本局限。

 

      # pragma comment 使連接器有命令行開關(guān)被顯示增加到鏈接步驟。 你可以進(jìn)入VC++ 項(xiàng)目| 設(shè)置 并且改變連接器命令行。

 

      你可以預(yù)定某一機(jī)制設(shè)置窗口句柄,例如

void SetWindow(HWND w) {hWnd = w; }

    

      但更經(jīng)常的是如下所示的與鉤子結(jié)合。

Sample: A Mouse Hook

header file (myhook.h)

 

      函數(shù) setMyHook 并且 clearMyHook 必須在此被聲明。這在我的另一文章中有詳細(xì)論述。“The Ultimate DLL Header File.”

#define UWM_MOUSEHOOK_MSG \
         _T("UMW_MOUSEHOOK-" \
        "{B30856F0-D3DD-11d4-A00B-006067718D04}")

source file (myhook.cpp)

#include "stdafx.h"
#include "myhook.h"
 
#pragma data_seg(".JOE")
HWND hWndServer = NULL;
#pragma data_seg()
#pragma comment("linker, /section:.JOE,rws")
 
HINSTANCE hInstance;
UINT HWM_MOUSEHOOK;
HHOOK hook;
 
// Forward declaration
static LRESULT CALLBACK msghook(int nCode, WPARAM wParam, LPARAM lParam);
/****************************************************************
*                               DllMain
* Inputs:
*       HINSTANCE hInst: Instance handle for the DLL
*       DWORD Reason: Reason for call
*       LPVOID reserved: ignored
* Result: BOOL
*       TRUE if successful
*       FALSE if there was an error (never returned)
* Effect:
*       Initializes the DLL.
****************************************************************/
 
BOOL DllMain(HINSTANCE hInst, DWORD Reason, LPVOID reserved)
{
 switch(Reason)
   { /* reason */
    //**********************************************
    // PROCESS_ATTACH
    //**********************************************
    case DLL_PROCESS_ATTACH:
       // Save the instance handle because we need it to set the hook later
       hInstance = hInst;
       // This code initializes the hook notification message
       UWM_MOUSEHOOK = RegisterWindowMessage(UWM_MOUSEHOOK_MSG);
       return TRUE;
 
    //**********************************************
    // PROCESS_DETACH
    //**********************************************
    case DLL_PROCESS_DETACH:
       // If the server has not unhooked the hook, unhook it as we unload
       if(hWndServer != NULL)
          clearMyHook(hWndServer);
       return TRUE;
   } /* reason */
/****************************************************************
*                               setMyHook
* Inputs:
*       HWND hWnd: Window whose hook is to be set
* Result: BOOL
*       TRUE if the hook is properly set
*       FALSE if there was an error, such as the hook already 
*             being set
* Effect:
*       Sets the hook for the specified window.
*       This sets a message-intercept hook (WH_GETMESSAGE)
*       If the setting is successful, the hWnd is set as the
*       server window.
****************************************************************/
 
__declspec(dllexport) BOOL WINAPI setMyHook(HWND hWnd)
  {
   if(hWndServer != NULL)
      return FALSE;
   hook = SetWindowsHookEx(
                           WH_GETMESSAGE,
                           (HOOKPROC)msghook,
                           hInstance,
                           0);
   if(hook != NULL)
     { /* success */
      hWndServer = hWnd;
      return TRUE;
     } /* success */
   return FALSE;

  } // SetMyHook

 

/****************************************************************
*                             clearMyHook
* Inputs:
*       HWND hWnd: Window whose hook is to be cleared
* Result: BOOL
*       TRUE if the hook is properly unhooked
*       FALSE if you gave the wrong parameter
* Effect:
*       Removes the hook that has been set.
****************************************************************/
__declspec(dllexport) BOOL clearMyHook(HWND hWnd)
   {
    if(hWnd != hWndServer)
       return FALSE;
    BOOL unhooked = UnhookWindowsHookEx(hook);
    if(unhooked)
       hWndServer = NULL;
    return unhooked;
   }
/****************************************************************
*                              msghook
* Inputs:
*       int nCode: Code value
*       WPARAM wParam: parameter
*       LPARAM lParam: parameter
* Result: LRESULT
*
* Effect:
*       If the message is a mouse-move message, posts it back to
*       the server window with the mouse coordinates
* Notes:
*       This must be a CALLBACK function or it will not work!
****************************************************************/
 
static LRESULT CALLBACK msghook(int nCode, WPARAM wParam, LPARAM lParam)
   {
    // If the value of nCode is < 0, just pass it on and return 0
    // this is required by the specification of hook handlers
    if(nCode < 0)
      { /* pass it on */
       CallNextHookEx(hook, nCode,
                   wParam, lParam);
       return 0;
      } /* pass it on */
 
    // Read the documentation to discover what WPARAM and LPARAM
    // mean. For a WH_MESSAGE hook, LPARAM is specified as being
    // a pointer to a MSG structure, so the code below makes that
    // structure available
 
    LPMSG msg = (LPMSG)lParam;
 
    // If it is a mouse-move message, either in the client area or
    // the non-client area, we want to notify the parent that it has
    // occurred. Note the use of PostMessage instead of SendMessage
    if(msg->message == WM_MOUSEMOVE ||
       msg->message == WM_NCMOUSEMOVE)
      PostMessage(hWndServer,
                  UWM_MOUSEMOVE,   
                  0, 0); 
 
    // Pass the message on to the next hook
    return CallNextHookEx(hook, nCode, 
                       wParam, lParam);
   } // msghook

The server application

在頭文件中,將下面的增加到類的protected段:

afx_msg LRESULT OnMyMouseMove(WPARAM,LPARAM);

application 文件中, 增加以下代碼到文件前部。

UINT UWM_MOUSEMOVE = ::RegisterWindowMessage(UWM_MOUSEMOVE_MSG);

MESSAGE_MAP, 增加以下代碼

 //{AFX_MSG comments:

ON_REGISTERED_MESSAGE(UWM_MOUSEMOVE, OnMyMouseMove)

In your application file, add the following function:

LRESULT CMyClass::OnMyMouseMove(WPARAM, LPARAM)
   {
    // ...do stuff here
    return 0;
   }

        上面是我寫的一個小程序。既然我為了鉤子花了n+1st 時間,我干脆給它一個好的用戶界面。 貓在窗口之內(nèi)盯著老鼠。小心! 當(dāng)老鼠足夠接近貓時并且它將捉住老鼠!

 

      你可以下載這個項(xiàng)目并建立它。 真正的關(guān)鍵是DLL 子工程項(xiàng)目; 其他的都不過是陪襯。有幾個其它的技術(shù)被用在這個例子里,包括各種各樣的圖畫技術(shù), ClipCursor SetCapture的用法,區(qū)域選擇、屏幕更新等等。,因此除了展示鉤子函數(shù)的使用以外,對初級程序員掌握窗口樣式設(shè)計編程也有一些價值。

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
HOOK編程 ----全局鉤子
Windows消息攔截技術(shù)的應(yīng)用
MFC(HOOK和數(shù)據(jù)庫訪問,孫鑫C 第二十講筆記整理)
鉤子技術(shù)
在游戲中切出外掛delphi代碼(hook)
編程MySpy開發(fā)手記
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服