在我的場景中,我有一個應用程式(我不擁有),它有多個視窗,并且同一個執行緒擁有多個視窗。因此,當我使用 安裝鉤子程序(從我自己的應用程式,使用包含此程序的 DLL 檔案)時SetWindowsHookEx,它將安裝一個鉤子,用于監視目標應用程式的同一執行緒擁有的所有視窗。
我想要實作的是,安裝的鉤子程序將有一個變數,例如targetHwnd. 一旦擁有它,它將忽略任何不是targetHwnd.
例如,我會有這樣的事情:
LRESULT CALLBACK GetMsgHookProc(int code, WPARAM wParam, LPARAM lParam)
{
// https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms644981(v=vs.85)#parameters
if (code == HC_ACTION)
{
const auto msg = (MSG*)lParam;
if (msg->hwnd != targetHwnd)
// We skip processing any other window that owned by this thread
return CallNextHookEx(hHook, code, wParam, lParam);
// Here I will do specific processing for the window I want
// ...
// ...
// ...
}
return CallNextHookEx(hHook, code, wParam, lParam);
}
問題是:我如何才能達到一個點,即帶有鉤子程序的 DLL 被注入了外部資訊,在我們的例子中是targetHwnd.
我沒有看到該函式SetWindowsHookEx具有用于自定義資料或類似引數的引數。
我想到的另一種方法是發送WM_COPYDATA到我需要的一個視窗(并且由我為其安裝掛鉤的外部應用程式執行緒擁有)。然后,GetMsgHookProc將通過WM_COPYDATA訊息獲取這些資料。如果在 DLL 中,targetHwnd是NULL,它將從lParam引數中獲取此資料。
但是,我怎么知道是我的應用程式發送了它還是以防萬一另一個應用程式也發送WM_COPYDATA到視窗?聽起來不安全..所以我認為我應該使用wParam(“傳遞資料的視窗的句柄”),然后通過呼叫GetClassName并檢查類名是否是我的唯一名稱來驗證它是否是從我的應用程式發送的預計。
但是我不確定從 DLL 中使用這些 API 是否安全,因為根據 MS 的說法,它可能是不安全的。
因此,如果您能給我一個我應該做什么的線索,以及我認為應該做的事情是否正確,這將對我有所幫助。
謝謝你。
uj5u.com熱心網友回復:
WM_COPYDATA跨執行緒邊界和 DLL 邊界使用是完全安全的。您可以使用該COPYDATASTRUCT::dwData欄位來標識該郵件是否屬于您不是,只需在該欄位中存盤一個唯一值即可。通常,RegisterWindowMessage()用于該目的。
但是,WM_COPYDATA對于這項任務來說有點矯枉過正。由于 anHWND直接放在WPARAMand 中LPARAM(由 證明WM_COPYDATA),您可以改為發送(甚至發布)自定義訊息,只有您的 DLL 鉤子知道如何處理的訊息。同樣,RegisterWindowMessage()可以用于該目的。
另一種選擇是使用共享記憶體,例如 viaCreateFileMapping()和MapViewOfFile()(或者, via #pragma data_seg,如果您的編譯器支持它)。安裝鉤子的應用程式可以分配一塊共享記憶體并將所需的存盤HWND在其中,然后注入的DLL就可以訪問它。請參閱在元件中使用共享記憶體。
uj5u.com熱心網友回復:
非常感謝 Remy Lebeau 幫助我找出完整解決方案的方向。但是,他的回答中有遺漏的部分,所以這是我找到的完整答案:
以下代碼是從我的應用程式中復制的。某些部分可能會丟失,例如類中的方法Win32Native。
Win32Native類中的所有方法都只是DllImport本機Win32API 的集合。所以你可以在 pvpoke 網站上找到它。- 有一個名為
WindowItem. 你不會在任何地方找到它。您應該知道的唯一相關資訊是此類具有成員:Hwnd- 我們掛鉤到的目標視窗的句柄,ProcessId這只是pid擁有該視窗的行程的句柄。我只在這段代碼中使用這些成員
安裝鉤子的主機應用程式:
using System;
using System.Runtime.InteropServices;
using WindowTop.Helpers;
using WindowTop.Managers;
namespace WindowTop.UI.Features.ShrinkBox
{
public class ShrinkInteractHookNative
{
[DllImport("ShrinkInteractHook.dll", CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr InstallHook(uint threadId);
}
public class ShrinkInteractHook : ShrinkInteractHookNative
{
public static IntPtr InstallHook(WindowItem windowItem)
{
var processId = windowItem.ProcessId;
var windowThread = Win32Native.GetWindowThreadProcessId(windowItem.Hwnd, ref processId);
var hHook = InstallHook(windowThread);
var WM_SEND_TARGET_HWND = Win32Native.RegisterWindowMessage("WINDOWTOP_WM_SEND_TARGET_HWND");
Win32Native.PostThreadMessage(windowThread, WM_SEND_TARGET_HWND, UIntPtr.Zero,
windowItem.Hwnd);
return hHook;
}
public static void UnInstallHook(IntPtr hHook)
{
Win32Native.UnhookWindowsHookEx(hHook);
}
}
}
這 DLL
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
HINSTANCE hInstHookDll = NULL;
HHOOK hHook = NULL;
HWND targetHwnd = NULL;
UINT WM_SEND_TARGET_HWND = 0;
LRESULT CALLBACK GetMsgHookProc(int code, WPARAM wParam, LPARAM lParam)
{
// https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms644981(v=vs.85)#parameters
if (LOWORD(msg->message) == WM_SEND_TARGET_HWND)
{
targetHwnd = (HWND)msg->lParam; // Here we get the targetHwnd
}
// Specific processing goes here:
// ...
// ...
// Pass this to the next hook
return CallNextHookEx(hHook, code, wParam, lParam);
}
extern "C" {
__declspec(dllexport) HHOOK __stdcall InstallHook(unsigned int threadId)
{
if (hHook != NULL)
{
UnhookWindowsHookEx(hHook);
hHook = NULL;
}
return SetWindowsHookEx(WH_GETMESSAGE, GetMsgHookProc, hInstHookDll, threadId);
}
}
BOOL APIENTRY DllMain(HANDLE hModule, DWORD reasonForCall, LPVOID lpReserved)
{
switch (reasonForCall)
{
case DLL_PROCESS_ATTACH:
hInstHookDll = (HINSTANCE)hModule;
WM_SEND_TARGET_HWND = RegisterWindowMessage(L"WINDOWTOP_WM_SEND_TARGET_HWND");
break;
case DLL_PROCESS_DETACH:
// TODO: Logic in case the dll was unloaded
break;
}
return TRUE;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/314739.html
標籤:登录
