在VC6中實現全局鉤子及枚舉窗口功能,設置timer

1、新建名稱爲CServerHook的MFC動態庫,選擇MFC擴展DLL選項,點擊完成。

2、系統自動生成ServerHook.cpp文件,但沒有ServerHook.h文件,該文件需要手動添加。

3、建立導出類CServerHook,ServerHook.h文件內容如下:

BOOL _declspec(dllexport)  CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam);枚舉窗口回調函數
void _declspec(dllexport)  gKillProcessByPid( DWORD dwPid );//根據進程ID銷燬該進程
void _declspec(dllexport)  gGetProcessByWindowTitle();//枚舉窗口名稱,得到對應進程Id
void _declspec(dllexport)  gSetFilePath(char* strPath);   //向dll中傳遞路徑
void _declspec(dllexport)  gSetTimer();                               //在dll中創建Timer

class __declspec(dllexport) CServerHook : public CObject
{
public:
 CServerHook();    //鉤子類的構造函數
 
 virtual ~CServerHook();  //鉤子類的析構函數
 
public:
 BOOL StartHook();   //安裝鉤子函數
 
 BOOL StopHook();   //卸載鉤子函數
};
4、ServerHook.cpp文件內容如下:

#include "stdafx.h"
#include <afxdllx.h>
#include "ServerHook.h"

#define _WIN32_WINNT 0x0500

#include <windows.h>
#include <stdio.h>

#define _SECOND 10000000

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#pragma data_seg("mydata")
HHOOK glhHook=NULL;    //安裝的鍵盤勾子句柄
HINSTANCE glhInstance=NULL;  //DLL實例句柄
char last_char ='q';
char g_chArr[MAX_PATH] = {0}; //保存傳遞進來的程序相對路徑
#pragma data_seg()

LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam);
static AFX_EXTENSION_MODULE ServerHookDLL = { NULL, NULL };
CString g_szCurPath = _T("");
CString g_strFlashMagazine = _T("");
CString g_strFlashDM = _T("");
DWORD wndTemp = 0;
int iFlag = 0;
HWND hwnd;
HWND m_hwndFind[100] = { NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
                      NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
       NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
       NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
       NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
       NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
       NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
       NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
       NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
       NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
int m_num = 0 ;
TCHAR m_store[MAX_PATH];

typedef struct _MYTimer {
   TCHAR *szText;
   DWORD dwValue;
} MYTIMER;

VOID CALLBACK TimerAPCProc(
   LPVOID lpArg,               // Data value
   DWORD dwTimerLowValue,      // Timer low value
   DWORD dwTimerHighValue )    // Timer high value

{
   MYTIMER *pMyData = (MYTIMER *)lpArg;

   printf( "Message: %s/nValue: %d/n/n", pMyData->szText,
          pMyData->dwValue );
   MessageBeep(0);

}

extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
 // Remove this if you use lpReserved
 UNREFERENCED_PARAMETER(lpReserved);

 if (dwReason == DLL_PROCESS_ATTACH)
 {
  TRACE0("SERVERHOOK.DLL Initializing!/n");
  
  // Extension DLL one-time initialization
  if (!AfxInitExtensionModule(ServerHookDLL, hInstance))
   return 0;

  // Insert this DLL into the resource chain
  // NOTE: If this Extension DLL is being implicitly linked to by
  //  an MFC Regular DLL (such as an ActiveX Control)
  //  instead of an MFC application, then you will want to
  //  remove this line from DllMain and put it in a separate
  //  function exported from this Extension DLL.  The Regular DLL
  //  that uses this Extension DLL should then explicitly call that
  //  function to initialize this Extension DLL.  Otherwise,
  //  the CDynLinkLibrary object will not be attached to the
  //  Regular DLL's resource chain, and serious problems will
  //  result.

  new CDynLinkLibrary(ServerHookDLL);
  glhInstance=hInstance;
 }
 else if (dwReason == DLL_PROCESS_DETACH)
 {
  TRACE0("SERVERHOOK.DLL Terminating!/n");
  // Terminate the library before destructors are called
  AfxTermExtensionModule(ServerHookDLL);
 }
 return 1;   // ok
}

CServerHook::CServerHook()
{
}

CServerHook::~CServerHook()
{
 if (glhHook)
 {
  UnhookWindowsHookEx(glhHook);
 }
}

BOOL CServerHook::StartHook()
{
 BOOL bResult=FALSE;
 glhHook=SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,glhInstance,0);
 /*============================================================
 HHOOK SetWindowsHookEx( int idHook,HOOKPROC lpfn, INSTANCE hMod,DWORD dwThreadId )
 參數idHook表示鉤子類型,它是和鉤子函數類型一一對應的。
 比如,WH_KEYBOARD表示安裝的是鍵盤鉤子,WH_MOUSE表示是鼠標鉤子等等。
 
 Lpfn是鉤子函數的地址。
  
 HMod是鉤子函數所在的實例的句柄。對於線程鉤子,該參數爲NULL;對於系統鉤子,
 該參數爲鉤子函數所在的DLL句柄。
  
 dwThreadId 指定鉤子所監視的線程的線程號。對於全局鉤子,該參數爲NULL。
   
 SetWindowsHookEx返回所安裝的鉤子句柄。
 值得注意的是線程鉤子和系統鉤子的鉤子函數的位置有很大的差別。
 線程鉤子一般在當前線程或者當前線程派生的線程內,
 而系統鉤子必須放在獨立的動態鏈接庫中,實現起來要麻煩一些。
 ===========================================================*/
 if(glhHook!=NULL)
  bResult=TRUE;
 return bResult;
}

//卸載鉤子
BOOL CServerHook::StopHook()
{
 BOOL bResult=FALSE;
 if(glhHook)
 {
  bResult= UnhookWindowsHookEx(glhHook);
  if(bResult)
   glhHook=NULL;
 }
 return bResult;
}

//鍵盤鉤子函數
LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)
{
 char ch = 0;
 
 if( ((DWORD)lParam&0x40000000) && (HC_ACTION==nCode) ) //有鍵按下
 {
  if( (wParam == VK_F4)||(wParam==VK_SPACE)||(wParam==VK_RETURN)||(wParam>=0x2f ) &&(wParam<=0x100) )
  {
   if (wParam==VK_RETURN)
   {
    ch='/n';
   }
   else
   {
    BYTE ks[256];
    GetKeyboardState(ks);
    WORD w;
    UINT scan=0;
    ToAscii(wParam,scan,ks,&w,0);
    ch =char(w);
   }
  }
  if (nCode >= 0)
  {
   if ( ch != last_char )
   {
    g_szCurPath = g_chArr;
    g_strFlashDM = g_chArr;
    g_strFlashDM += _T("flash//DM//");
    g_strFlashMagazine = g_chArr;
    g_strFlashMagazine += _T("flash//Magazine//");
    gGetProcessByWindowTitle();
    switch(iFlag)
    {
    case 1:
     if (ch == 'a')
     {
      last_char = ch;
      ShellExecute(NULL,"open",g_strFlashDM + _T("bank.exe"),NULL,g_strFlashDM,SW_SHOW);
      gKillProcessByPid(wndTemp);
      
     }
     else if (ch == 'b')
     {
      last_char = ch;
      ShellExecute(NULL,"open",g_strFlashDM + _T("discount.exe"),NULL,g_strFlashDM,SW_SHOW);
      gKillProcessByPid(wndTemp);
     }
     else if (ch == 'c')
     {
      //last_char = ch;
      ShellExecute(NULL,"open",g_szCurPath + _T("BirthFlash.exe"),NULL,g_szCurPath,SW_SHOW);
      gKillProcessByPid(wndTemp);
     }
     else if (ch == 'd')
     {
      //last_char = ch;
      ShellExecute(NULL,"open",g_szCurPath + _T("GamesFlash.exe"),NULL,g_szCurPath,SW_SHOW);
      gKillProcessByPid(wndTemp);
     }
     else if (ch == 'f')
     {
      last_char = ch;
      ShellExecute(NULL,"open",g_szCurPath + _T("Terminal.exe"),NULL,g_szCurPath,SW_SHOW);
      gKillProcessByPid(wndTemp);
     }
     else if (ch == 'q')
     {
      last_char = ch;
      ShellExecute(NULL,"open",g_strFlashMagazine + _T("magazine.exe"),NULL,g_strFlashMagazine,SW_SHOW);
      gKillProcessByPid(wndTemp);
     }
     break;
    case 2:
     break;
    case 3:
     break;
    case 4:
     if (ch == 'q')
     {
      last_char = ch;
      ShellExecute(NULL,"open",g_strFlashMagazine + _T("magazine.exe"),NULL,g_strFlashMagazine,SW_SHOW);
      gKillProcessByPid(wndTemp);
     }
     break;
    default:
     break;
    }
   }
  }
 }

 return CallNextHookEx(glhHook,nCode,wParam,lParam);
}

//枚舉窗口
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
  DWORD wndPid;
  CString Title;
  if(::GetWindowLong(hwnd,GWL_STYLE)& WS_VISIBLE)
  {
   m_hwndFind[m_num] = hwnd;//record the HWND handle into array
   m_num++;//count start
  }
  // This gets the windows handle and pid of enumerated window.
  GetWindowThreadProcessId( hwnd, &wndPid );

  // This gets the windows title text
  // from the window, using the window handle
  CWnd::FromHandle( hwnd )->GetWindowText(Title);
  BOOL bFlag = FALSE;
  if (Title.CompareNoCase("Terminal") == 0)
  {
   bFlag = TRUE;
   iFlag = 4;
   wndTemp = wndPid;
  }
  else if( Title.CompareNoCase( "Macromedia Flash Player 8" ) == 0)
  {
  bFlag = TRUE;
  iFlag = 1;
  wndTemp = wndPid;
  }
  else if (Title.CompareNoCase("SelBirth") == 0 || Title.CompareNoCase("BirthFlash") == 0)
  {
   bFlag = TRUE;
   iFlag = 2;
   wndTemp = wndPid;
  }
  else if (Title.CompareNoCase("SelGames") == 0 || Title.CompareNoCase("GamesFlash") == 0)
  {
   bFlag = TRUE;
   iFlag = 3;
   wndTemp = wndPid;
  }
  else
  {
   iFlag = 0;
  }
  //  this makes sure that the PID matches that PID we started, and window
  // text exists, before we kill it . I don't think this is really needed,
  // I included it because some apps have more than one window.
  if ( bFlag)
  {
    return false;
  }
  else
  {
    // Keep enumerating
    return true;
  }
}

//根據進程ID終止進程
void gKillProcessByPid(DWORD dwPid)
{
 HANDLE ps = OpenProcess( SYNCHRONIZE|PROCESS_TERMINATE,FALSE, dwPid);
 DWORD wExit;
   ::GetExitCodeProcess(ps,&wExit);
   ::TerminateProcess(ps,wExit);
}

void gGetProcessByWindowTitle()
{
 EnumWindows( EnumWindowsProc, NULL );
}

//設置程序相對路徑
void gSetFilePath( char* strPath)
{
 strcpy( g_chArr, strPath );
}

void gSetTimer()
{
   HANDLE          hTimer;
   BOOL            bSuccess;
   __int64         qwDueTime;
   LARGE_INTEGER   liDueTime;
   MYTIMER          TimerData;
   TCHAR           szError[255];

   TimerData.szText = "This is my data.";
   TimerData.dwValue = 100;

   if ( hTimer = CreateWaitableTimer(
           NULL,                   // Default security attributes
           FALSE,                  // Create auto-reset timer
           "MyTimer" ) )           // Name of waitable timer
   {
    // Create an integer that will be used to signal the timer
    // 5 seconds from now.
    qwDueTime = -5 * _SECOND;
   
    // Copy the relative time into a LARGE_INTEGER.
    liDueTime.LowPart  = (DWORD) ( qwDueTime & 0xFFFFFFFF );
    liDueTime.HighPart = (LONG)  ( qwDueTime >> 32 );
   
    bSuccess = SetWaitableTimer(
     hTimer,           // Handle to the timer object
     &liDueTime,       // When timer will become signaled
     2000,             // Periodic timer interval of 2 seconds
     TimerAPCProc,     // Completion routine
     &TimerData,          // Argument to the completion routine
     FALSE );          // Do not restore a suspended system
   
    if ( bSuccess )
    {
   do
   {
    gGetProcessByWindowTitle();
    if (iFlag == 0)
    {
     g_strFlashMagazine = g_chArr;
     g_strFlashMagazine += _T("flash//Magazine//");
     ShellExecute(NULL,"open",g_strFlashMagazine + _T("magazine.exe"),NULL,g_strFlashMagazine,SW_SHOW);
     Sleep(2000);
    }
    SleepEx(INFINITE,TRUE);
   } while(1);
    }
    else
    {
    wsprintf( szError, "SetWaitableTimer failed with Error /
     %d.", GetLastError() );
    MessageBox( NULL, szError, "Error", MB_ICONEXCLAMATION );
    }
   }
   else
   {
      wsprintf( szError, "CreateWaitableTimer failed with Error %d.",
          GetLastError() );
      MessageBox( NULL, szError, "Error", MB_ICONEXCLAMATION );
   }
}

 5、在ServerHook.def中加入:

SECTIONS
mydata READ WRITE SHARED

6、編譯生成dll和LIB文件。

7、在另一個工程中對其進行調用,即可實現鉤子功能。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章