win32 - 使用SetWindowHookEx注入global hook

写下这是为了自己复习的。

主要实现的是给File Explorer注入鼠标钩子,以检测鼠标是否在File Explorer上点击

.cpp

#include <Windows.h>
#include <stdio.h>
#include <psapi.h>
#include <shlwapi.h>
#include <tchar.h>

#pragma comment(lib,"Kernel32.lib")
#pragma comment(lib,"shlwapi.lib")
#pragma comment(linker, "/SECTION:.shared,RWS")

using namespace std;

DWORD  dwPID;


LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
    if (message == WM_DESTROY) {
        PostQuitMessage(0);
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
};
HINSTANCE hinst;

int main()
{
    Sleep(3000); //用作选择file explorer,可以用定时器代替
    CHAR lpFileName[MAX_PATH] = { 0 };
    HANDLE hProcess;
    HWND   hwnd = GetForegroundWindow();
    DWORD threadID = GetWindowThreadProcessId(hwnd, &dwPID);
    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, dwPID);
    GetModuleFileNameEx(hProcess, NULL, lpFileName, _countof(lpFileName));
    PathStripPath(lpFileName);

    if (_tcscmp(_T("explorer.exe"), lpFileName) == 0) {
        _tprintf(_T("explorer window found"));
    }
    else {
        _tprintf(_T("foreground window was not explorer window"));
    }
    CloseHandle(hProcess);

    HINSTANCE hinstDLL = LoadLibrary(TEXT("DLL.dll")); //这里需要新创建的dll的路径
    HHOOK(*AttachHookProc)(DWORD);
    AttachHookProc = (HHOOK(*)(DWORD)) GetProcAddress(hinstDLL, "AttachHook");


    HHOOK HOOK = AttachHookProc(threadID);

    int err = GetLastError();//检测是否有错误

    MSG msg = {};

    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

.dll

// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"

#include <Windows.h>
#include <stdio.h>

HMODULE thisModule;
HHOOK hook;
LRESULT CALLBACK LaunchListener(int nCode, WPARAM wParam, LPARAM lParam);

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    thisModule = hModule;
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

#ifdef __cplusplus    //If used by C++ code.
extern "C" {        //we need to export the C interface
#endif
    _declspec(dllexport) HHOOK AttachHook(DWORD threadID) {
        hook = SetWindowsHookEx(WH_MOUSE, LaunchListener, thisModule, threadID); 

        return hook;
    }
#ifdef __cplusplus
}
#endif
LRESULT CALLBACK LaunchListener(int nCode, WPARAM wParam, LPARAM lParam) {
    // process event here
    if (nCode >= 0)
    {
        switch (wParam & 0x0001)
        {
        case MK_LBUTTON:
            {
                MessageBox(NULL, TEXT("Click"), NULL, MB_OK);
            }
            break;
        }
    }
    
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

 相关: How do I unhook a global hook from another process?

             FreeLibrary failed

对于不需要的钩子,可以对其unhook。

原理类似于下面的例子:

#include <windows.h>

HMODULE hModule = NULL;
HANDLE hTERM = NULL;
HHOOK hCBT = NULL;
HHOOK hShell = NULL;

static bool Continue()
{
    return (WAIT_TIMEOUT == WaitForSingleObject(hTERM, 0));
}

LRESULT CALLBACK _cbtProc(int code, WPARAM wParam, LPARAM lParam)
{
    if (Continue()) {
        // Handle the message ...
    }
    return CallNextHookEx(NULL, code, wParam, lParam);
}

LRESULT CALLBACK _shellProc(int code, WPARAM wParam, LPARAM lParam)
{
    if (Continue()) {
        // Handle the message ...
    }
    return CallNextHookEx(NULL, code, wParam, lParam);
}

__declspec(dllexport) BOOL WINAPI InstallHooks()
{
    if (!Continue())
        return FALSE;

    if (!hCBT)
        hCBT = SetWindowsHookEx(WH_CBT, _cbtProc, hModule, 0);

    if (!hShell)
        hShell = SetWindowsHookEx(WH_SHELL, _shellProc, hModule, 0);

    return ((hCBT) && (hShell)) ? TRUE : FALSE;
}

__declspec(dllexport) void WINAPI RemoveHooks()
{
    if (hTERM)
        SetEvent(hTERM);

    if (hCBT) {
        UnhookWindowsHookEx(hCBT);
        hCBT = NULL;
    }

    if (hShell) {
        UnhookWindowsHookEx(hShell);
        hShell = NULL;
    }
}

BOOL WINAPI DllMain(HMODULE hinstDLL, DWORD fdwReason, void* lpvReserved)
{
    hModule = hinstDLL;

    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            hTERM = CreateEvent(NULL, TRUE, FALSE, TEXT("{0C3ED513-F38C-4996-8130-F9A3C93D890B}"));
            if (!hTERM) return FALSE;
            break;

        case DLL_PROCESS_DETACH:
            if (hTERM) {
                CloseHandle(hTERM);
                hTERM = NULL;
            }
            break;
    }

    return TRUE;
}

需要钩子的时候,在主程序中调用InstallHooks, 不需要的时候,调用RemoveHooks...

 

新的例子: 使用WH_CBT阻止浏览器最大化

DLL:

// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include "stdio.h"
#include <string>
#include <windows.h>

#pragma warning(disable:4996)

HHOOK hCBT = NULL;
static HWND hTarget, hTarget1;
BOOL done = FALSE;
WNDPROC g_OldWndProc;
HMODULE thisModule;

LRESULT CALLBACK NewWndProc(HWND hwnd, UINT mesg, WPARAM wParam, LPARAM lParam)
{
    switch (mesg)
    {
    case WM_SYSCOMMAND:
    {
        if (wParam == SC_MAXIMIZE)
        {
            MessageBox(NULL, L"SC_MAXIMIZE", L" ", MB_OK);
            return 1;
        }
    }
    break;
    }

    return CallWindowProc(g_OldWndProc, hwnd, mesg, wParam, lParam);
}


LRESULT CALLBACK _cbtProc(int code, WPARAM wParam, LPARAM lParam)
{
    FILE* logfile;
    char buffer[256] = {};
    char buffer_[256] = {};
    char buffer1[256] = {};
    if (code < 0) return CallNextHookEx(0, code, wParam, lParam);

 //   if (code == HCBT_ACTIVATE)
 //   {         
 //       CBTACTIVATESTRUCT *cb = (CBTACTIVATESTRUCT*)lParam;      
 //       int m = (int)cb->hWndActive;
 //       int n = (int)hTarget;
 //       int x = (int)(HWND)(wParam);
 //       logfile = fopen("log.txt", "w");
 //       sprintf(buffer, "%d", m);
 //       fprintf(logfile, "cb->hWndActive:");
 //       fprintf(logfile, buffer);
 //       fprintf(logfile, "\n");
 //       sprintf(buffer_, "%d", n);
 //       fprintf(logfile, "hTarget:");
 //       fprintf(logfile, buffer_);
 //       fprintf(logfile, "\n");
 //       sprintf(buffer1, "%d", x);
 //       fprintf(logfile, "(HWND)(wParam):");
 //       fprintf(logfile, buffer1);
 //       fprintf(logfile, "\n");
 //       if ((HWND)(wParam))
 //       {
 ////           MessageBox(NULL, L"activate", L" ", MB_OK);
 //           if (done == FALSE)
 //           {                
 //               g_OldWndProc = (WNDPROC)(SetWindowLongPtr((HWND)(wParam), GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(NewWndProc)));
 //               done = TRUE;
 //           }
 //       }
 //   }
    if (code == HCBT_MINMAX)
    {
        if (LOWORD(lParam) == SW_SHOWMAXIMIZED)
        {
            return 1;
        }
        
    }
    return CallNextHookEx(0, code, wParam, lParam);
}

#ifdef __cplusplus    //If used by C++ code.
extern "C" {        //we need to export the C interface
#endif
    __declspec(dllexport) BOOL WINAPI InstallHooks(HWND HandleofTarget)
    {
        wchar_t buffer[100] = {};
        hTarget = HandleofTarget;
        hTarget1 = HandleofTarget;
        
        DWORD tid = GetWindowThreadProcessId(hTarget, NULL);
        hCBT = SetWindowsHookEx(WH_CBT, _cbtProc, thisModule, tid);

        return (hCBT) ? TRUE : FALSE;
    }
#ifdef __cplusplus
}
#endif

#ifdef __cplusplus    //If used by C++ code.
extern "C" {        //we need to export the C interface
#endif
    __declspec(dllexport) void WINAPI RemoveHooks()
    {   
         UnhookWindowsHookEx(hCBT);
         MessageBox(NULL, L"unhook", L" ", MB_OK);
         hCBT = NULL;
    }
#ifdef __cplusplus
}
#endif

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    thisModule = hModule;
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

.cpp

#include <Windows.h>
#include <stdio.h>
#include <psapi.h>
#include <shlwapi.h>
#include <tchar.h>

#pragma comment(lib,"Kernel32.lib")
#pragma comment(lib,"shlwapi.lib")
#pragma comment(linker, "/SECTION:.shared,RWS")

using namespace std;
HINSTANCE hinstDLL;
typedef void (*RemoveHooks)();

DWORD __stdcall CreateThreadFunc(LPVOID)
{
    while (1)
    {
        if (GetAsyncKeyState(0x50) & 0x0001)
        {
            RemoveHooks removeHooks = (RemoveHooks)GetProcAddress(hinstDLL, "RemoveHooks");
            removeHooks();
        }
    }
    return 0;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
    if (message == WM_DESTROY) {      
        PostQuitMessage(0);
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
};
HINSTANCE hinst;

int main()
{
    HWND hwnd = FindWindow(L"Chrome_WidgetWin_1", L"Google Translate - Google Chrome");
 
    CreateThread(NULL, 0, CreateThreadFunc, 0, 0, 0);

    hinstDLL = LoadLibrary(TEXT("D:\\Start from 11.2\\WM_CBT_DLL\\x64\\Debug\\WM_CBT_DLL.dll")); 
    BOOL(*InstallHooks)(HWND);
    InstallHooks = (BOOL(*)(HWND)) GetProcAddress(hinstDLL, "InstallHooks");
    
    BOOL l = InstallHooks(hwnd);

    int err = GetLastError();

    MSG msg = {};

    while (GetMessage(&msg, NULL, 0, 0)) {       
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

 

posted @ 2019-12-11 08:59  strive-sun  阅读(732)  评论(0编辑  收藏  举报