在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、在另一个工程中对其进行调用,即可实现钩子功能。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值