I would like to create global WH_CBT hook using winapi. I create dll with this hook. When I using this
dll in other application ( this app load dll and start hook - let it name be abc.exe ) I can load that dll, get functions ( with hook and unhook ) and see the output, but only from that abc.exe's thread. I would like to see messages like HCBT_CREATEWND from other windows ( not only from abc.exe window ). I set the fourth arg in SetWindowsHookEx to 0, so I except to set the global hook.
In abc.h:
HINSTANCE hDll;
typedef void( * MYPROC )( void );
MYPROC funHook, funUnhook;
In abc.exe window constructor (abc.cpp):
hDll = LoadLibrary( L"probaHook" );
if( hDll )
{
funHook =( MYPROC ) GetProcAddress( hDll, (LPCSTR) "hook" );
funUnhook = ( MYPROC ) GetProcAddress( hDll, (LPCSTR) "unhook" );
qDebug()<<funHook<<funUnhook;
if( funHook )
{
funHook();
}
}
In abc.exe window destructor (abc.cpp):
if( funUnhook )
{
funUnhook();
}
FreeLibrary( hDll );
In probahook.h ( file with dll declaration functions ):
#ifndef PROBAHOOK_H
#define PROBAHOOK_H
#include "probaHook_global.h"
#include "windows.h"
LRESULT CALLBACK cbtHookProc( int code, WPARAM wParam, LPARAM lParam );
extern "C" PROBAHOOK_EXPORT void hook( void );
extern "C" PROBAHOOK_EXPORT void unhook( void );
class PROBAHOOK_EXPORT ProbaHook
{
public:
ProbaHook();
};
#endif // PROBAHOOK_H
In probaHook_global.h:
#ifndef PROBAHOOK_GLOBAL_H
#define PROBAHOOK_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(PROBAHOOK_LIBRARY)
# define PROBAHOOK_EXPORT Q_DECL_EXPORT
#else
# define PROBAHOOK_EXPORT Q_DECL_IMPORT
#endif
#endif // PROBAHOOK_GLOBAL_H
In probahook.cpp:
#include "probahook.h"
#include <QDebug>
#include <QFile>
HHOOK hhook = NULL;
HINSTANCE hInst = NULL;
LRESULT CALLBACK cbtHookProc( int code, WPARAM wParam, LPARAM lParam )
{
if( code < 0 ) return CallNextHookEx( 0, code, wParam, lParam );
qDebug()<<code;
if( code == HCBT_CREATEWND )
{
QFile file(R"(C:\Users\tom\Desktop\def.txt)");
file.open(QIODevice::WriteOnly | QIODevice::Append);
file.write(QString::number(GetCurrentThreadId()).toStdString().c_str());
file.write("\n");
file.close();
return 0;
}
return CallNextHookEx( 0, code, wParam, lParam );
}
ProbaHook::ProbaHook(){}
BOOLEAN APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
{
hInst = hModule;
switch( ul_reason_for_call )
{
case DLL_PROCESS_ATTACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
void hook( void )
{
hhook = SetWindowsHookEx( WH_CBT, cbtHookProc, hInst, 0 );
}
void unhook(void)
{
UnhookWindowsHookEx( hhook );
}
The output from def.txt is:
17192
17192
17192
17192
17192
17192
17192 is my abc.exe thread. Of course when abc.exe is running I try open other windows.
qDebug() in cbtHookProc of course produce output like: 4,6,0, but only from abc.exe window.
Related
I'm using IContextMenu with "delete" verb to erase items from recycle bin, but it brings up the UI dialog even if I useCMIC_MASK_FLAG_NO_UI flag. Is there another way to delete files from recycle bin without showing the dialog?
IContextMenu* contextMenu;
recycleBin->GetUIObjectOf(0, 1, (LPCITEMIDLIST*)(&pidl), IID_IContextMenu, 0, (LPVOID *)&contextMenu);
CMINVOKECOMMANDINFO ci;
memset(&ci, 0, sizeof(ci));
ci.fMask = CMIC_MASK_FLAG_NO_UI;
ci.cbSize = sizeof(CMINVOKECOMMANDINFO);
ci.lpVerb = "delete";
contextMenu->InvokeCommand(&ci);
contextMenu->Release();
The full code including recycle bin object initialization and items enumeration is on gist
You can install a WH_CBT hook, and in its callback watch for an nCode of HCBT_CREATEWND. If you get a matching class name ('#32770 (Dialog)' ?) and a matching title either return a nonzero value from the callback, you can send BM_CLICK to click Yes button and the dialog will be closed automatically.
Code Sample:
main.cpp
#include <iostream>
#include <windows.h>
#include <Ole2.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <string>
#pragma comment(lib,"Shlwapi.lib")
HHOOK g_hhook;
int main()
{
OleInitialize(0);
HINSTANCE hinstDLL = LoadLibrary(TEXT("D:\\xxx\\Dll_WH_CBT\\Debug\\Dll_WH_CBT.dll"));
HHOOK(*AttachHookProc)(DWORD);
AttachHookProc = (HHOOK(*)(DWORD)) GetProcAddress(hinstDLL, "AttachHook");
void(*RemoveHooks)(DWORD);
RemoveHooks = (void(*)(DWORD))GetProcAddress(hinstDLL, "RemoveHooks");
IShellFolder* desktop;
if (FAILED(SHGetDesktopFolder(&desktop))) {
std::cerr << "Failed to get desktop fodler" << std::endl;
return -1;
}
...
IEnumIDList* enumFiles;
if (FAILED(recycleBin->EnumObjects(0, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS |
SHCONTF_INCLUDEHIDDEN, &enumFiles)))
{
std::cerr << "Could not enumerate recycle bin objects" << std::endl;
recycleBin->Release();
return -1;
}
AttachHookProc(0);
...
RemoveHooks(0);
enumFiles->Release();
recycleBin->Release();
OleUninitialize();
return 0;
}
Dll:
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include <Windows.h>
HMODULE thisModule;
HHOOK g_hhook;
LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
switch (nCode)
{
case HCBT_CREATEWND:
{
HWND File_Window = FindWindow(L"#32770", L"Delete File");
HWND Folder_Window = FindWindow(L"#32770", L"Delete Folder");
if (File_Window)
{
HWND yes = FindWindowEx(File_Window, NULL, L"Button", L"&Yes");
SendMessage(yes, BM_CLICK, 0, 0);
SendMessage(yes, BM_CLICK, 0, 0);
}
if (Folder_Window)
{
HWND yes = FindWindowEx(Folder_Window, NULL, L"Button", L"&Yes");
SendMessage(yes, BM_CLICK, 0, 0);
SendMessage(yes, BM_CLICK, 0, 0);
}
break;
}
default:
break;
}
return CallNextHookEx(g_hhook, nCode, wParam, lParam);
}
#ifdef __cplusplus //If used by C++ code.
extern "C" { //we need to export the C interface
#endif
_declspec(dllexport) HHOOK AttachHook(DWORD threadID) {
g_hhook = SetWindowsHookEx(WH_CBT, CBTProc, thisModule, threadID);
return g_hhook;
}
#ifdef __cplusplus
}
#endif
extern "C" { //we need to export the C interface
__declspec(dllexport) void RemoveHooks(DWORD)
{
UnhookWindowsHookEx(g_hhook);
}
}
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;
}
I'm trying to use SetWindowsHookEx to install WH_CBT hook on global to inject the DLL into other process. Now I have the inject.exe, ExampleWindow.exe, inject.dll, let me show you the code.
1.code piece of inject.exe
#include <windows.h>
int main()
{
HHOOK hhook = NULL;
HMODULE dll = LoadLibrary(_T("D:\\projects\\CppDemon\\Release\\HookDemoDll.dll"));
HOOKPROC pfn = (HOOKPROC)GetProcAddress(dll, "MyCBTProc");
if (pfn == NULL)
{
printf("can not get MyCBTProc,press any key to exit\n");
getchar();
return 0;
}
printf("press any key to continue hook\n");
getchar();
hhook = SetWindowsHookEx(WH_CBT, pfn, dll, 0);
if (NULL == hhook)
{
printf("%d\n", GetLastError());
}
printf("press any key to unhook\n");
getchar();
UnhookWindowsHookEx(hhook);
return 0;
}
2.code piece of inject.dll
#ifdef __cplusplus
extern "C"
{
#endif
extern "C" __declspec(dllexport) LRESULT MyCBTProc(_In_ int nCode, _In_ WPARAM wParam, _In_ LPARAM lParam);
#ifdef __cplusplus
}
#endif
LRESULT MyCBTProc(_In_ int nCode, _In_ WPARAM wParam, _In_ LPARAM lParam)
{
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
DWORD pid = 0;
TCHAR buffer[128] = { 0 };
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
pid = GetCurrentProcessId();
_stprintf_s(buffer, 128, _T("[+] PID = %d"), pid);
OutputDebugString(buffer);
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
The ExampleWindow.exe is a test case for inject when the named window is created.
When I run inject.exe and everything goes well, the inject.dll has been loaded and the the debug message is output correct, and the PCHUNTER(this is an ARK tool) can detect the WH_CBT message hook in module inject.exe. Then, I run the ExampleWindow.exe, there also can output the debug message.
After this action, I refresh the message hook windows in PCHUNTER ,the WH_CBT hook message has disappeared from the control, and the inject.dll not injected in the ExampleWindow.exe at all.THis is not my expect result.
I don't know how this happens. I hope someone can help me find the cause of this problem.
I have code for a C++ Win32 Wrapper Class which i am fiddling with. Since I'm just trying to use handler's, i removed the WindowProcedure and just used a message router. And somehow things are getting buggy.
Now with just the message router the title of the WindowClass which i have tired to make doesn't display the title name of the window.
And somehow i can't seem to get the background color to change.
Main.cpp
#include "BaseWindow.h"
#include "GameWindow.h"
int APIENTRY WinMain ( HINSTANCE h_instance, HINSTANCE h_prev_instance, LPSTR lp_cmd_line, int n_cmd_show ) {
// Create the Game Window
GameWindow game_window ( h_instance, TEXT ( "GameWindow" ) );
game_window.Register ();
// Create the Base Window
BaseWindow base_window ( TEXT ( "BaseWindow" ), game_window.ClassName () );
base_window.Create ();
base_window.Show ();
// Pump Messages
MSG messages;
int status;
while ( ( status = GetMessage ( &messages, 0, 0, 0 ) ) != 0 ) {
if ( status == -1 ) {
// Break;
break;
}
TranslateMessage ( &messages );
DispatchMessage ( &messages );
}
return messages.wParam;
}
AbstractWindow.h
#pragma once
#ifndef __ABSTRACT_WINDOW_H__
#define __ABSTRACT_WINDOW_H__
#include <Windows.h>
class AbstractWindow {
public:
AbstractWindow ();
~AbstractWindow ();
virtual bool Create ();
static LRESULT CALLBACK MessageRouter ( HWND, UINT, WPARAM, LPARAM );
protected:
HWND hwnd_;
DWORD style_ex_;
LPCTSTR class_name_;
LPCTSTR window_name_;
DWORD style_;
int x_;
int y_;
int width_;
int height_;
HWND parent_;
HMENU menu_;
HINSTANCE h_instance_;
LPVOID param_;
// Default Handlers
virtual bool OnCreate ( HWND ) = 0;
virtual bool OnCommand ( int, int ) = 0;
virtual bool OnDestroy () = 0;
virtual bool EraseBackground ( HWND, WPARAM ) = 0;
virtual bool LeftButtonUp () = 0;
};
#endif // !__ABSTRACT_WINDOW_H__
AbstractWindow.cpp
#include "AbstractWindow.h"
AbstractWindow::AbstractWindow () {}
AbstractWindow::~AbstractWindow () {}
bool AbstractWindow::Create () {
hwnd_ = CreateWindowEx (
style_ex_,
class_name_,
window_name_,
style_,
x_,
y_,
width_,
height_,
parent_,
menu_,
h_instance_,
this // Pointer to this class instance
);
return ( !hwnd_ ? false : true );
}
LRESULT CALLBACK AbstractWindow::MessageRouter ( HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param ) {
AbstractWindow* abstract_window = 0;
if ( message == WM_NCCREATE ) {
abstract_window = ( AbstractWindow* ) ( ( LPCREATESTRUCT ( l_param ) )->lpCreateParams );
SetWindowLong ( hwnd, GWL_USERDATA, long ( abstract_window ) );
abstract_window->OnCreate ( hwnd );
}
else {
abstract_window = ( AbstractWindow* ) ( GetWindowLong ( hwnd, GWL_USERDATA ) );
if ( abstract_window ) {
switch ( message ) {
case WM_COMMAND:
return abstract_window->OnCommand ( LOWORD ( w_param ), HIWORD ( w_param ) );
case WM_DESTROY:
return abstract_window->OnDestroy ();
case WM_ERASEBKGND:
return abstract_window->EraseBackground ( hwnd, w_param );
case WM_LBUTTONUP:
return abstract_window->LeftButtonUp ();
default:
return DefWindowProc ( hwnd, message, w_param, l_param );
}
}
else {
return DefWindowProc ( hwnd, message, w_param, l_param );
}
}
}
BaseWindow.h
#pragma once
#ifndef __BASE_WINDOW_H__
#define __BASE_WINDOW_H__
#include <Windows.h>
#include "AbstractWindow.h"
class BaseWindow : public AbstractWindow {
public:
BaseWindow ();
~BaseWindow ();
BaseWindow ( const TCHAR*, const TCHAR* );
// Display the window onto the screen while updating the client area
void Show ();
private:
virtual bool OnCreate ( HWND );
virtual bool OnCommand ( int, int );
virtual bool OnDestroy ();
virtual bool EraseBackground ( HWND, WPARAM );
virtual bool LeftButtonUp ();
};
#endif // !__BASE_WINDOW_H__
BaseWindow.cpp
#include "BaseWindow.h"
BaseWindow::BaseWindow () {}
BaseWindow::~BaseWindow () {}
BaseWindow::BaseWindow ( const TCHAR* window_name, const TCHAR* class_name ) : AbstractWindow () {
// Member variables are declaried in AbstractWindow as Protected
window_name_ = window_name;
class_name_ = class_name;
// Get the module handle for the window currently running
h_instance_ = GetModuleHandle ( NULL );
style_ = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
x_ = CW_USEDEFAULT;
y_ = CW_USEDEFAULT;
width_ = CW_USEDEFAULT;
height_ = CW_USEDEFAULT;
parent_ = NULL;
menu_ = NULL;
}
void BaseWindow::Show () {
// hwnd_ is from AbstractWindow Class
ShowWindow ( hwnd_, SW_SHOW );
UpdateWindow ( hwnd_ );
}
// Handlers
bool BaseWindow::OnCreate (HWND hwnd) {
MessageBox ( hwnd, TEXT ( "[BaseWindow] Window has been successfully created!" ), TEXT ( "SUCCESS" ), MB_OK );
return true;
}
bool BaseWindow::OnCommand ( int ctrl_id, int notify_code ) {
// Lower 16 bits specifies the element the mouse was used on
// Upper 16 bits specifies the mouse properties
// ctrl_id = Lower
// notify_code = Upper
return true;
}
bool BaseWindow::OnDestroy () {
PostQuitMessage ( 0 );
return true;
}
bool BaseWindow::EraseBackground ( HWND hwnd, WPARAM w_param) {
RECT rect;
GetClientRect ( hwnd, &rect );
FillRect ( ( HDC ) w_param, &rect, GetSysColorBrush ( COLOR_BTNFACE ) );
return true;
}
bool BaseWindow::LeftButtonUp () {
return true;
}
GameWindow.h
#pragma once
#ifndef __GAME_WINDOW_H__
#define __GAME_WINDOW_H__
#include <Windows.h>
#include "AbstractWindow.h"
class GameWindow : protected WNDCLASSEX {
public:
GameWindow ();
~GameWindow ();
GameWindow ( HINSTANCE, const TCHAR* );
virtual bool Register ();
virtual const TCHAR* ClassName () const;
protected:
UINT cb_size_;
UINT style_;
WNDPROC lpfn_wnd_proc_;
int cb_cls_extra_;
int cb_wnd_extra_;
HINSTANCE h_instance_;
HICON h_icon_;
HCURSOR h_cursor_;
HBRUSH hbr_background_;
LPCTSTR lpsz_menu_name_;
LPCTSTR lpsz_class_name_;
HICON h_icon_sm_;
};
#endif // !__GAME_WINDOW_H__
GameWindow.cpp
#include "GameWindow.h"
GameWindow::GameWindow () {}
GameWindow::~GameWindow () {}
GameWindow::GameWindow ( HINSTANCE h_instance, const TCHAR* class_name ) {
// All messages belonging to this Window Class will get sent to MsgRouter
hInstance = h_instance;
lpszClassName = class_name;
lpfnWndProc = AbstractWindow::MessageRouter;
lpszMenuName = NULL;
cbSize = sizeof ( WNDCLASSEX );
cbClsExtra = NULL;
cbWndExtra = NULL;
style = CS_HREDRAW | CS_VREDRAW;
hIcon = LoadIcon ( NULL, IDI_APPLICATION );
hIconSm = LoadIcon ( NULL, IDI_APPLICATION );
hCursor = LoadCursor ( NULL, IDC_HAND );
hbrBackground = ( HBRUSH ) GetStockObject ( COLOR_BTNFACE );
}
const TCHAR* GameWindow::ClassName () const {
return lpszClassName;
}
bool GameWindow::Register () {
return ( ( RegisterClassEx ( this ) ) ? true : false );
}
Your MessageRouter is missing default processing. Add DefWindowProc as shown
LRESULT CALLBACK AbstractWindow::MessageRouter ( HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param ) {
AbstractWindow* abstract_window = 0;
if ( message == WM_NCCREATE ) {
abstract_window = ( AbstractWindow* ) ( ( LPCREATESTRUCT ( l_param ) )->lpCreateParams );
SetWindowLong ( hwnd, GWL_USERDATA, long ( abstract_window ) );
abstract_window->OnCreate ( hwnd );
return DefWindowProc(hwnd, message, w_param, l_param);//ADD THIS LINE
}
...
For background, you can either handle WM_ERASEBKGND or you can set hbrBackground
Method 1: handle WM_ERASEBKGND
virtual LRESULT EraseBackground(HWND hwnd, WPARAM w_param)
{
RECT rect;
GetClientRect(hwnd, &rect);
FillRect((HDC)w_param, &rect, GetSysColorBrush(COLOR_BTNFACE));
return 1;
}
Method 2: set hbrBackground and let window do the rest
hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
virtual LRESULT EraseBackground(HWND hwnd, WPARAM w_param)
{
//let window do this
return DefWindowProc(hwnd, WM_ERASEBKGND, w_param, 0);
}
.........
Edit #2
class AbstractWindow
{
virtual void OnPaint()=0;
...
};
AbstractWindow::MessageRouter()
{
case WM_PAINT:
abstract_window->OnPaint();
return 0;
...
}
void GameWindow::OnPaint()
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
TextOut(hdc, 0, 0, "Hello, Windows!", 15);
EndPaint(hwnd, &ps);
}
I am trying to install global keyboard hook and on every DLL_PROCESS_ATTACH Notification try to subclass foreground window. I have separate exe and dll for both 64 bit and 32 bit application. I works ok if only one type (32 or 64 bit) exe and dll pair but not working for both at a time. I was not getting DLL_ATTACH_NOTIFICATION for 32 bit applications if I use 32 bit hook first and then 64 bit.Due to this i was unable to subclass 32 bit application.
sample code for DLL both for 32 and 64 bit with different name
`//#include "stdafx.h"
#include <tchar.h>
#include <process.h>
#pragma data_seg(".HOOKDATA")//Shared data among all instances.
HHOOK g_hKbdHook = NULL;
#pragma data_seg()
#pragma comment(linker, "/SECTION:.HOOKDATA,RWS")//linker directive
#pragma data_seg(".HOOKDATA32")//Shared data among all instances.
HHOOK g_hKbdHook32 = NULL;
#pragma data_seg()
#pragma comment(linker, "/SECTION:.HOOKDATA32,RWS")//linker directive
HINSTANCE g_hInstance = NULL;
HINSTANCE g_hInstance32 = NULL;
HWND hwndKeyFocused = NULL;
static HWND hwndOld;
static HWND hwndFocused;
static WNDPROC oldWindowProc;
BOOL APIENTRY
DllMain(
HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
DWORD dw;
int iRet;
HWND hwnd;
BOOL boIs32bit;
DWORD dwProcID;
HANDLE hProcess;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
dwProcID = GetCurrentProcessId();
hProcess = OpenProcess(
PROCESS_VM_READ |
PROCESS_VM_WRITE |
PROCESS_VM_OPERATION |
PROCESS_CREATE_THREAD |
PROCESS_QUERY_INFORMATION,
FALSE,
dwProcID
);
IsWow64Process(
hProcess,
&boIs32bit
);
if (TRUE == boIs32bit)
{
g_hInstance32 = (HINSTANCE)hModule;;
}
else
{
g_hInstance = (HINSTANCE)hModule;
}
hwnd = GetForegroundWindow();
oldWindowProc =(WNDPROC) SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)HackingWndProc);
dw = GetLastError();
hwndOld = hwnd;
break;
case DLL_PROCESS_DETACH:
SetWindowLongPtr(hwndOld, GWLP_WNDPROC, (LONG_PTR)oldWindowProc );
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
g_hKbdHook = NULL;
return TRUE;
}
BOOLEAN __stdcall
Init(
)
{
g_hKbdHook = NULL;
g_hKbdHook = SetWindowsHookEx(WH_KEYBOARD, ProcessKey, g_hInstance, NULL);
if(g_hKbdHook==NULL)
{
return FALSE;
}
return TRUE;
}
BOOLEAN __stdcall
Init32(
)
{
g_hKbdHook32 = NULL;
g_hKbdHook32 = SetWindowsHookEx(WH_KEYBOARD, ProcessKey32, g_hInstance32, NULL);
if(g_hKbdHook32 == NULL)
{
return FALSE;
}
return TRUE;
}
BOOLEAN __stdcall
DeInit(
)
{
UnhookWindowsHookEx(g_hKbdHook);
if (NULL != g_hKbdHook32)
{
UnhookWindowsHookEx(g_hKbdHook32);
}
return TRUE;
}
LRESULT CALLBACK
ProcessKey(
int ncode,
WPARAM wparam,
LPARAM lparam
)
{
return (CallNextHookEx(g_hKbdHook, ncode, wparam, lparam));//pass control to next hook in the hook chain.
}
LRESULT CALLBACK HackingWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return CallWindowProc(
oldWindowProc,
hWnd,
message,
wParam,
lParam
);
}
LRESULT CALLBACK
ProcessKey32(
int ncode,
WPARAM wparam,
LPARAM lparam
)
{
return (CallNextHookEx(g_hKbdHook32, ncode, wparam, lparam));//pass control to next hook in the hook chain.
}
enter code here
`
I'm trying to hook a button click in a mfc window.And I used WM_COMMAND and WM_NOTIFY.For test, if the button is clicked, the hook must create a messagebox. The problem is that it doesn't react to button clicks.
Here's the code for reacting to WM_COMMAND and WM_NOTIFY:
LPMSG msg = (LPMSG)lParam;
switch( msg->message )
{
case WM_COMMAND:
MessageBox( NULL,"HOOK","YOOOO",MB_ICONEXCLAMATION );
break;
case WM_NOTIFY:
MessageBox( NULL,"HOOK","YOOOOO",MB_ICONEXCLAMATION );
break;
}
And here's the code to hole dll:
#include <Windows.h>
#include "FindingWindow.h"
#pragma comment( linker,"/SECTION:.SHARED,RWS" )
#pragma data_seg( ".SHARED" )
CaptureTextWindow* ctw;
HHOOK hook = 0;
HMODULE hInstance = 0;
HWND hWndServer = NULL;
#pragma data_seg()
static LRESULT CALLBACK msghook(int nCode, WPARAM wParam, LPARAM lParam);
__declspec(dllexport) BOOL clearMyHook(HWND hWnd);
BOOL APIENTRY DllMain( HINSTANCE hInst, DWORD ul_reason_for_call, LPVOID lpReserved )
{
switch( ul_reason_for_call )
{
case DLL_PROCESS_ATTACH:
hInstance = hInst;
return TRUE;
case DLL_PROCESS_DETACH:
if(hWndServer != NULL)
clearMyHook(hWndServer);
return TRUE;
}
return TRUE;
}
__declspec(dllexport) BOOL WINAPI setMyHook(HWND hWnd)
{
if(hWndServer != NULL)
return FALSE;
hook = SetWindowsHookEx(
WH_CALLWNDPROC,
(HOOKPROC)msghook,
hInstance,
0);
if(hook != NULL)
{ /* success */
hWndServer = hWnd;
return TRUE;
} /* success */
return FALSE;
}
__declspec(dllexport) BOOL clearMyHook(HWND hWnd)
{
if(hWnd != hWndServer)
return FALSE;
BOOL unhooked = UnhookWindowsHookEx(hook);
if(unhooked)
hWndServer = NULL;
return unhooked;
}
static LRESULT CALLBACK msghook( int nCode, // hook code
WPARAM wParam , // message identifier
LPARAM lParam )
{
if( nCode < 0 )
{
CallNextHookEx( hook, nCode, wParam, lParam );
return 0;
}
LPMSG msg = (LPMSG)lParam;
switch( msg->message )
{
case WM_COMMAND:
MessageBox( NULL,"HOOK","YOOOO",MB_ICONEXCLAMATION );
break;
case WM_NOTIFY:
MessageBox( NULL,"HOOK","YOOOOO",MB_ICONEXCLAMATION );
break;
}
return CallNextHookEx( hook, nCode, wParam, lParam );
}
I used not only WM_COMMAND cause I thought mb it will work, but it didn't.Thanks for answer.
The lParam for a WH_CALLWNDPROC hook is of type CWPSTRUCT. Your CallWndProc should look like this:
// ...
const CWPSTRUCT& cwps = *(CWPSTRUCT*)lParam;
switch ( cwps.message ) {
case WM_COMMAND:
MessageBox( ... );
break;
// ...