系统范围的挂钩不在主程序外运行

时间:2013-11-19 02:34:39

标签: c++ winapi hook

我在系统范围内编写Hook Mouse(当鼠标悬停在屏幕上的任何组件上时,它的Handle,classname,wndproc将显示在我的程序中)。

但是当我将程序中的鼠标移到主程序之外时,我的程序中的系统范围挂钩不会运行

我成功创建了DLL文件,但是不明白为什么它只能作为本地钩子运行(它在本地我的程序运行良好 - 我程序的屏幕区域)。

这是hookDLL.cpp(DLL文件)的来源:

#include "stdafx.h"
#include "Win32_Iczelion_HookDLL.h"

#define WM_MOUSEHOOK WM_USER+10

HINSTANCE hInstance;
HHOOK hHook;
HWND hWnd;

EXPORT HHOOK CALLBACK InstallHook(HWND);
EXPORT void CALLBACK UninstallHook(void);
EXPORT LRESULT CALLBACK MouseProc(int, WPARAM, LPARAM);

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

EXPORT HHOOK CALLBACK InstallHook(HWND hwnd)
{
    hWnd = hwnd;
    hHook = SetWindowsHookEx (WH_MOUSE, (HOOKPROC)MouseProc, hInstance, NULL); 
    return hHook;
}

EXPORT void CALLBACK UninstallHook()
{
    UnhookWindowsHookEx(hHook);
}

EXPORT void test()
{
    MessageBox(NULL, L"yeah", L"yeah", MB_OK);
}

EXPORT LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    CallNextHookEx(hHook, nCode, wParam, lParam);
    POINT pt = {0};
    GetCursorPos(&pt);
    HANDLE handle = WindowFromPoint(pt);
    PostMessage(hWnd, WM_MOUSEHOOK, (WPARAM)handle, 0);
    return 0;
}

这是hook.cpp(主程序)的来源:

#include "stdafx.h"
#include "Win32_Iczelion_Hook.h"
#include "Win32_Iczelion_HookDLL.h"

#define WM_MOUSEHOOK WM_USER+10

#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst;                                // current instance
TCHAR szTitle[MAX_LOADSTRING];                  // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name
HWND hWndEHandle;
HWND hWndEClassName;
HWND hWndEWndProc;
HWND hWndBHook;
HWND hWndBExit;
HHOOK hHook;
BOOL HookFlag = FALSE;

// Forward declarations of functions included in this code module:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPTSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: Place code here.
    MSG msg;
    HACCEL hAccelTable;

    // Initialize global strings
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadString(hInstance, IDC_WIN32_ICZELION_HOOK, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // Perform application initialization:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WIN32_ICZELION_HOOK));

    // Main message loop:
    while (GetMessage(&msg, NULL, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}

ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WIN32_ICZELION_HOOK));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = MAKEINTRESOURCE(IDC_WIN32_ICZELION_HOOK);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassEx(&wcex);
}

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, 600, 300, NULL, NULL, hInstance, NULL);

   hWndEHandle = CreateWindowEx(NULL, L"Edit", NULL,
                        WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOHSCROLL,
                        100,35,345,25,hWnd,(HMENU)IDC_HANDLE,hInstance,NULL);
   hWndEClassName = CreateWindowEx(NULL, L"Edit", NULL,
                        WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOHSCROLL,
                        100,65,200,25,hWnd,(HMENU)IDC_CLASSNAME,hInstance,NULL);
   hWndEWndProc = CreateWindowEx(NULL, L"Edit", NULL,
                        WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOHSCROLL,
                        100,95,200,25,hWnd,(HMENU)IDC_WNDPROC,hInstance,NULL);

   hWndBHook = CreateWindowEx(NULL, L"Button", L"Hook", 
                        WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
                        305,65,140,25,hWnd,(HMENU)IDC_HOOK,hInstance,NULL);
   hWndBExit = CreateWindowEx(NULL, L"Button", L"Exit", 
                        WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
                        305,95,140,25,hWnd,(HMENU)IDC_EXIT,hInstance,NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;
    LPWSTR buffer = 0;
    RECT rect;

    switch (message)
    {
    case WM_CREATE:
        GetWindowRect(hWnd, &rect);
        SetWindowPos(hWnd, HWND_TOPMOST, rect.left, rect.top, rect.right, rect.bottom, SWP_SHOWWINDOW);
        break;
    case WM_CLOSE:
        if (HookFlag==TRUE)
            UninstallHook();
        DestroyWindow(hWnd);
    case WM_MOUSEHOOK:
    {
        wchar_t buffer[256];
        wsprintfW(buffer, L"%p", wParam);
        SetDlgItemText(hWnd, IDC_HANDLE, buffer);

        GetClassName((HWND)wParam, buffer, 128);
        SetDlgItemText(hWnd, IDC_CLASSNAME, buffer);

        DWORD buffer2 = GetClassLong((HWND)wParam,GCL_WNDPROC);
        wsprintfW(buffer, L"%p", buffer2);
        SetDlgItemText(hWnd, IDC_WNDPROC, buffer);
        break;
    }
    case WM_COMMAND:
    {
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // Parse the menu selections:

        if (wmEvent==BN_CLICKED)
        {
            if (wmId==IDC_HOOK)
            {
                if (HookFlag==FALSE)
                {
                    if (InstallHook(hWnd))
                    {
                        HookFlag = TRUE;
                        SetDlgItemText(hWnd, IDC_HOOK, L"Un hook");
                    }
                }
                else
                {
                     UninstallHook();
                     SetDlgItemText(hWnd,IDC_HOOK,L"Hook");
                     HookFlag = FALSE;
                     SetDlgItemText(hWnd,IDC_CLASSNAME,NULL);
                     SetDlgItemText(hWnd,IDC_HANDLE,NULL);
                     SetDlgItemText(hWnd,IDC_WNDPROC,NULL);
                }
            }
            else if (wmId==IDC_EXIT)
            {
                SendMessage(hWnd,WM_CLOSE,0,0);
            }
        }
        switch (wmId)
        {
        case IDM_ABOUT:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break;
    }
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        // TODO: Add any drawing code here...
        EndPaint(hWnd, &ps);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

任何人都可以帮助我。

2 个答案:

答案 0 :(得分:3)

上次编辑:更正后的代码。

如果它们与主进程具有相同的位数(并且如果它们获得鼠标),则由Windows在其他进程中加载​​DLL。结果:Dll中的全局hWnd变量始终为NULL,PostMessage失败。

建议:

1 请务必检查API的返回代码。你应该注意到PostMessage失败了。

2 当您要在DLL中使用PostMessage时,如果您看到NULL hWnd,请使用FindWindow获取HWND并将其存储在{{1}中下一次。

MouseProc DLL CallBack的新版本:

hWnd

编辑:确保从重建DLL的文件夹中运行程序(EXE)。创建一个空解决方案(SLN)并在其中添加2个项目(vcxproj)。删除所有“旧”EXE和DLL。重建。

编辑添加了ScreenShot: EXE显示Explorer文件夹栏的类名

enter image description here

答案 1 :(得分:1)

当DLL从另一个程序加载时(当你将鼠标悬停在主程序之外时),hWnd为NULL,所以你必须使用FindWindow在PostMessage之前获取主程序的hWnd值。