hook dll
// FrameHook.h
#pragma once
#ifdef FRAMEHOOK_EXPORTS
#define FRAMEHOOK_API __declspec(dllexport)
#else
#define FRAMEHOOK_API __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C" {
#endif
FRAMEHOOK_API BOOL InstallHook(HWND hwnd, PTCHAR procName = NULL);
FRAMEHOOK_API BOOL UnInstallHook();
#ifdef __cplusplus
}
#endif
// FrameHook.cpp
// FrameHook.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "FrameHook.h"
#include "resource.h"
#include <process.h>
#include <Tlhelp32.h>
#include <string>
#include <tchar.h>
#include <sstream>
#pragma data_seg("Segment")
HINSTANCE g_hInst; // 载入dll的应用程序实例
HWND g_hApp = NULL; // 被hook的应用程序句柄
HWND g_hDlg = NULL; // 应用程序边框句柄
HHOOK g_cbtHook = NULL; // WH_CBT
HHOOK g_callWndProcHook = NULL; // WH_CALLWNDPROC
const UINT g_space = 15; // 边框宽度
const UINT g_millisecond = 300; // 边框异步显示间隔
#pragma data_seg()
#pragma comment(linker, "/SECTION:Segment,RWS")
static LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam);
#define WM_CREATE_FRAME_DIALOG (WM_USER + 123)
inline void DebugLog(const char *msg, ...)
{
char buf[1024] = {0};
va_list ap;
va_start(ap, msg);
vsprintf_s(buf, sizeof(buf), msg, ap);
va_end(ap);
OutputDebugStringA(buf);
}
void ShowFrameDlg();
void HideFrameDlg();
void ShowAutoSizeFrameDlg();
void MoveFrameDlg(RECT rc);
void AsyncShowFrameDlg(UINT milliseconds, BOOL isNormal = TRUE);
void SetAppFocus();
BOOL IsScreenRect(RECT rc);
FRAMEHOOK_API BOOL InstallHook(HWND hwnd, PTCHAR procName)
{
g_hApp = hwnd;
DWORD pid = GetWindowThreadProcessId(hwnd, NULL);
g_cbtHook = SetWindowsHookEx(WH_CBT, (HOOKPROC)CBTProc, g_hInst, pid);
g_callWndProcHook = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)CallWndProc, g_hInst, pid);
if (NULL==g_cbtHook || NULL==g_callWndProcHook) {
DebugLog("SetWindowsHookEx error, errcode:%d\n", GetLastError());
return FALSE;
}
SendMessage(g_hApp, WM_CREATE_FRAME_DIALOG, 0, 0);
DebugLog("FrameHook install success\n");
return TRUE;
}
FRAMEHOOK_API BOOL UnInstallHook()
{
if (g_hDlg) {
SendMessage(g_hDlg, WM_CLOSE, 0, 0);
DebugLog("DestroyWindow, errcode:%d\n", GetLastError());
}
if (g_cbtHook) {
if (!UnhookWindowsHookEx(g_cbtHook)) {
DebugLog("UnhookWindowsHookEx error, CBTHOOK, errcode:%d\n", GetLastError());
}
}
if (g_callWndProcHook) {
if (!UnhookWindowsHookEx(g_callWndProcHook)) {
DebugLog("UnhookWindowsHookEx error, WNDPROCHOOK, errcode:%d\n", GetLastError());
}
}
return TRUE;
}
LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if ((nCode < 0) || ((HWND)wParam != g_hApp)) {
return CallNextHookEx(g_cbtHook, nCode, wParam, lParam);
}
switch (nCode)
{
case HCBT_ACTIVATE:
{
if (IsWindowVisible(g_hDlg)) {
LPCBTACTIVATESTRUCT p = (LPCBTACTIVATESTRUCT)lParam;
if (g_hDlg == p->hWndActive) {
//ShowAutoSizeFrameDlg();
//if (g_hApp != GetFocus()) {
// SetAppFocus();
//}
} else if (0==p->hWndActive) {
ShowAutoSizeFrameDlg();
if (g_hApp != GetFocus()) {
SetAppFocus();
}
}
}
}
break;
case HCBT_MINMAX:
{
DebugLog("CBTProc, HCBT_MINMAX\n");
SetWindowPos(g_hDlg, g_hApp, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW);
UINT sw = LOWORD(lParam);
DebugLog("CBTProc, HCBT_MINMAX, %d\n", sw);
if (sw == SW_RESTORE) {
if (IsZoomed(g_hApp)) {
AsyncShowFrameDlg(g_millisecond, FALSE);
} else {
AsyncShowFrameDlg(g_millisecond);
}
} else if (sw == SW_MAXIMIZE) {
HideFrameDlg();
}
}
break;
case HCBT_MOVESIZE:
{
PRECT p = (PRECT)lParam;
MoveFrameDlg(*p);
}
break;
case HCBT_DESTROYWND:
DebugLog("CBTProc, HCBT_DESTROYWND\n");
HideFrameDlg();
break;
}
return CallNextHookEx(g_cbtHook, nCode, wParam, lParam);
}
INT_PTR CALLBACK FrameDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CTLCOLORDLG:
{
static HBRUSH bkBrush = CreateSolidBrush(RGB(181, 230, 29));
return INT_PTR(bkBrush);
}
case WM_CLOSE:
DebugLog("FrameDlgProc, WM_CLOSE\n");
DestroyWindow(hwndDlg);
break;
}
return 0;
}
LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode < 0) {
return CallNextHookEx(g_callWndProcHook, nCode, wParam, lParam);
}
PCWPSTRUCT p = (PCWPSTRUCT)lParam;
if (g_hApp == p->hwnd) {
switch (p->message)
{
case WM_CREATE_FRAME_DIALOG:
{
g_hDlg = CreateDialog(g_hInst, MAKEINTRESOURCE(IDD_FRAMEDLG), 0, FrameDlgProc);
ShowAutoSizeFrameDlg();
SetAppFocus();
DebugLog("AppHandle:0x%x, FrameHandle:0x%x\n", g_hApp, g_hDlg);
}
break;
case WM_MOVING:
case WM_SIZING:
HideFrameDlg();
break;
case WM_CLOSE:
DebugLog("CallWndProc, WM_CLOSE\n");
HideFrameDlg();
case WM_DESTROY:
DebugLog("CallWndProc, WM_DESTROY\n");
HideFrameDlg();
break;
default:
break;
}
}
return CallNextHookEx(g_callWndProcHook, nCode, wParam, lParam);
}
void ShowFrameDlg()
{
ShowWindow(g_hDlg, SW_SHOW);
}
void HideFrameDlg()
{
ShowWindow(g_hDlg, SW_HIDE);
}
void ShowAutoSizeFrameDlg()
{
RECT appRect;
GetWindowRect(g_hApp, &appRect);
if (IsScreenRect(appRect)) {
return;
}
RECT dlgRect;
dlgRect.left = appRect.left - g_space;
dlgRect.top = appRect.top - g_space;
dlgRect.right = appRect.right + g_space;
dlgRect.bottom = appRect.bottom + g_space;
SetWindowPos(g_hDlg, HWND_TOP, dlgRect.left, dlgRect.top,
dlgRect.right-dlgRect.left, dlgRect.bottom-dlgRect.top, SWP_SHOWWINDOW | SWP_NOZORDER);
}
void MoveFrameDlg(RECT dstRect)
{
if (IsScreenRect(dstRect)) {
return;
}
RECT dlgRect;
dlgRect.left = dstRect.left - g_space;
dlgRect.top = dstRect.top - g_space;
dlgRect.right = dstRect.right + g_space;
dlgRect.bottom = dstRect.bottom + g_space;
SetWindowPos(g_hDlg, HWND_TOP, dlgRect.left, dlgRect.top,
dlgRect.right-dlgRect.left, dlgRect.bottom-dlgRect.top, SWP_SHOWWINDOW);
}
typedef struct tagThreadParam
{
UINT times;
BOOL isNormal;
}ThreadParam, *PThreadParam;
UINT WINAPI AsyncShowFrameDlgProc(void *data)
{
PThreadParam p = (PThreadParam)data;
Sleep(p->times);
if (p->isNormal) {
ShowFrameDlg();
} else {
ShowAutoSizeFrameDlg();
}
return 0;
}
void AsyncShowFrameDlg(UINT milliseconds, BOOL isNormal)
{
static ThreadParam tp;
tp.times = milliseconds;
tp.isNormal = isNormal;
HANDLE h = (HANDLE)_beginthreadex(NULL, 0, AsyncShowFrameDlgProc, (PThreadParam)&tp, 0, NULL);
CloseHandle(h);
}
void SetAppFocus()
{
SetFocus(g_hApp);
}
BOOL IsScreenRect(RECT rc)
{
RECT screenRect;
SystemParametersInfo(SPI_GETWORKAREA, 0, &screenRect, 0);
if (rc.left==screenRect.left && rc.right==screenRect.right &&
rc.top==screenRect.top && rc.bottom==screenRect.bottom) {
return TRUE;
}
return FALSE;
}
使用hook dll,显示载入:
class FHookLauncher
{
public:
FHookLauncher()
: m_hModule(NULL)
, m_installHookFunc(NULL)
, m_uninstallHookFunc(NULL)
{
const TCHAR name[] = TEXT("FrameHook64.dll");
m_hModule = LoadLibrary(name);
if (m_hModule) {
m_installHookFunc = (InstallHookFunc)GetProcAddress(m_hModule, "InstallHook");
m_uninstallHookFunc = (UnInstallHookFunc)GetProcAddress(m_hModule, "UnInstallHook");
}
}
~FHookLauncher()
{
if (m_hModule) {
FreeLibrary(m_hModule);
m_hModule = NULL;
}
}
void Install(HWND hwnd)
{
if (m_installHookFunc) {
m_installHookFunc(hwnd, NULL);
}
}
void Uninstall()
{
if (m_uninstallHookFunc) {
m_uninstallHookFunc();
}
}
private:
FHookLauncher(const FHookLauncher&);
FHookLauncher& operator=(const FHookLauncher&);
private:
HMODULE m_hModule;
typedef BOOL (*InstallHookFunc)(HWND hwnd, PTCHAR procName);
typedef BOOL (*UnInstallHookFunc)();
InstallHookFunc m_installHookFunc;
UnInstallHookFunc m_uninstallHookFunc;
};
需要注意的是32位的dll只能给32位应用程序加边框,对于64位应用程序需要一个64位版本的dll,
如果只有一个32位程序我怎样才能让这个64位hook dll给64位的应用程序加边框呢?
方法是:增加一个中间层64位程序,用这个程序来加载64位hook dll,而我们的32位应用程序可以通过窗口句柄发消息给64位中间程序
来控制64位hook dll的加载和卸载。