SetWindowsHookEx to monitor Windows open and close - windows

I took this example code from here that hooks a function to intercept keyboard events, and it works:
#include <Windows.h>
// variable to store the HANDLE to the hook. Don't declare it anywhere else then globally
// or you will get problems since every function uses this variable.
HHOOK _hook;
// This struct contains the data received by the hook callback. As you see in the callback function
// it contains the thing you will need: vkCode = virtual key code.
KBDLLHOOKSTRUCT kbdStruct;
// This is the callback function. Consider it the event that is raised when, in this case,
// a key is pressed.
LRESULT __stdcall HookCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= 0)
{
// the action is valid: HC_ACTION.
if (wParam == WM_KEYDOWN)
{
// lParam is the pointer to the struct containing the data needed, so cast and assign it to kdbStruct.
kbdStruct = *((KBDLLHOOKSTRUCT*)lParam);
// a key (non-system) is pressed.
if (kbdStruct.vkCode == VK_F1)
{
// F1 is pressed!
MessageBox(NULL, "F1 is pressed!", "key pressed", MB_ICONINFORMATION);
}
}
}
// call the next hook in the hook chain. This is nessecary or your hook chain will break and the hook stops
return CallNextHookEx(_hook, nCode, wParam, lParam);
}
void SetHook()
{
// Set the hook and set it to use the callback function above
// WH_KEYBOARD_LL means it will set a low level keyboard hook. More information about it at MSDN.
// The last 2 parameters are NULL, 0 because the callback function is in the same thread and window as the
// function that sets and releases the hook. If you create a hack you will not need the callback function
// in another place then your own code file anyway. Read more about it at MSDN.
if (!(_hook = SetWindowsHookEx(WH_KEYBOARD_LL, HookCallback, NULL, 0)))
{
MessageBox(NULL, "Failed to install hook!", "Error", MB_ICONERROR);
}
}
void ReleaseHook()
{
UnhookWindowsHookEx(_hook);
}
void main()
{
// Set the hook
SetHook();
// Don't mind this, it is a meaningless loop to keep a console application running.
// I used this to test the keyboard hook functionality. If you want to test it, keep it in ;)
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
}
}
I am trying to make the similar code works for WH_GETMESSAGE to intercept WH_CREATE and WH_DESTROY messages, but it didn't work:
#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <psapi.h>
#include <iostream>
HHOOK _hook;
LRESULT CALLBACK GetMsgProc(_In_ int nCode, _In_ WPARAM wParam, _In_ LPARAM lParam)
{
std::cout << "Enter hook\n";
if (nCode >= 0)
{
// the action is valid: HC_ACTION.
std::cout << "HC_ACtION\n";
if (wParam != PM_REMOVE) return NULL;
MSG m = *((MSG*)lParam);
std::cout << "Message received\n";
TCHAR Buffer[MAX_PATH];
if (GetModuleFileNameEx(m.hwnd, 0, Buffer, MAX_PATH))
{
// At this point, buffer contains the full path to the executable
MessageBox(NULL, Buffer, L"key pressed", MB_ICONINFORMATION);
}
else
{
// You better call GetLastError() here
}
//CloseHandle(Hand);
}
// call the next hook in the hook chain. This is nessecary or your hook chain will break and the hook stops
return CallNextHookEx(_hook, nCode, wParam, lParam);
}
void SetHook()
{
if (!(_hook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, NULL, 0)))
{
MessageBox(NULL, L"Failed to install hook!", L"Error", MB_ICONERROR);
}
}
void ReleaseHook()
{
UnhookWindowsHookEx(_hook);
}
void main()
{
// Set the hook
SetHook();
// Don't mind this, it is a meaningless loop to keep a console application running.
// I used this to test the keyboard hook functionality. If you want to test it, keep it in ;)
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
}
}
MSDN specifies to use the function GetMsgProc with a predefined signature, but I don't see it does anything.

Related

Is it possible to subclass a web browser using winapi c++?

The main goal is to block maximalize web browser window using subclassing and dll.
I have 2 apps: injector and the dll.
In injector app I load that dll, find window by title, get functions from dll and execute that functions ( their names are hook and unhook ) from dll. So this is standard injector. Of course I check is something NULL and I don't get any errors.
In dll I have 5 functions:
dllMain (here I only set global hInstance variable, which is in shared memory ):
BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
{
switch(fdwReason)
{
case DLL_PROCESS_ATTACH:
{
if (hInstance == NULL)
{
hInstance = hinstDLL;
}
break;
}
...
}
return TRUE;
}
Hook ( HandleofTarget is the HWND, which I get from FindWindow ; I use this function in injector ):
extern "C" __declspec(dllexport) bool hook( HWND HandleofTarget)
{
hTarget=HandleofTarget;
hhook=SetWindowsHookEx(WH_CBT,cbtHookProc,hInstance, GetWindowThreadProcessId(hTarget,NULL));
if(hhook==NULL)
return 0;
else
return 1;
}
Unhook ( here I unhook hooks - I use this function in injector):
extern "C" __declspec(dllexport) void unhook(void)
{
if(hhook != NULL)
UnhookWindowsHookEx( hhook );
}
cbtHookProc ( hook callback, where I change window procedure ):
LRESULT CALLBACK cbtHookProc( int code, WPARAM wParam, LPARAM lParam )
{
if( code < 0 ) return CallNextHookEx( 0, code, wParam, lParam );
if (code == HCBT_ACTIVATE)
{
if((HWND)(wParam)==hTarget)
{
if(done == FALSE)
{
g_OldWndProc =(WNDPROC)(SetWindowLongPtr ( (HWND)(wParam), GWLP_WNDPROC,reinterpret_cast<LONG_PTR>( NewWndProc )));
done = TRUE;
}
}
}
return CallNextHookEx( 0, code, wParam, lParam );
}
NewWndProc ( new Window procedure, where I would like to block maximalize ):
LRESULT CALLBACK NewWndProc( HWND hwnd, UINT mesg, WPARAM wParam, LPARAM lParam )
{
switch( mesg )
{
case WM_SYSCOMMAND:
{
if(wParam == SC_MAXIMIZE)
{
return 1;
}
}
break;
}
return CallWindowProc( g_OldWndProc, hwnd, mesg, wParam, lParam );
}
When I test this dll with other apps - it works. When I use this dll with web browser like Internet Edge and Google Chrome - it doesn't works. That web browser, which I try injected works slower, but I can still maximalize that window. When I debuq dll, in web browser after SetWindowsHookEx I see that hook is not NULL, but my code doesn't go to cbtHookProc. What is going on with web browser?
UPDATE:
One more time - thank you Strive Sun - MSFT for helping me.
I change the lines in cbtHookProc, but it still doesn't work. My cbtHookProc is don't called by webBrowser - that is problem.
When I looked at your gif I see something what I don't have and I think that is the problem. My injector app looks like this:
hDll = LoadLibrary( L"dllka10" );
hHookedWindow=FindWindow(TEXT("Chrome_WidgetWin_1"),TEXT("Nowa karta - Google Chrome"));
if( hDll && hHookedWindow)
{
qDebug()<<"hDll and hHookedWindow are not NULL!";
funHook =( MYPROC2 ) GetProcAddress( hDll, (LPCSTR) "hook" );
funUnhook = ( MYPROC ) GetProcAddress( hDll, (LPCSTR) "unhook" );
if( funHook )
{
qDebug()<<funHook(hHookedWindow);
}
}
I don't use CreateThread(). Is it important here?
UPDATED 2
LRESULT CALLBACK cbtHookProc( int code, WPARAM wParam, LPARAM lParam )
{
if( code < 0 ) return CallNextHookEx( 0, code, wParam, lParam );
std::fstream file;
file.open("C:\\Users\\tom\\Desktop\\logs.txt",std::ios::out|std::ios::app);
file<<"In cbtHook function!"<<std::endl;
file.close();
if (code == HCBT_MINMAX)
{
if (LOWORD(lParam) == SW_SHOWMAXIMIZED)
{
return 1;
}
}
return CallNextHookEx( 0, code, wParam, lParam );
}
When I run chrome application - my logs.txt is empty. When I run other app - I have logs.
UPDATED 3
In my dll I have:
#ifdef __GNUC__
HWND hTarget __attribute__((section (".shared"), shared)) =NULL;
HWND hApp __attribute__((section (".shared"), shared)) = NULL;
bool done __attribute__((section (".shared"), shared)) =FALSE;
HINSTANCE hInstance __attribute__((section (".shared"), shared)) =NULL;
HHOOK hhook __attribute__((section (".shared"), shared)) = NULL;
WNDPROC g_OldWndProc __attribute__((section (".shared"), shared)) = NULL;
#endif
#ifdef _MSC_VER
#pragma data_seg(".shared")
HWND hTarget=NULL;
HWND hApp = NULL;
bool done=FALSE;
HINSTANCE hInstance=NULL;
HHOOK hhook = NULL;
WNDPROC g_OldWndProc = NULL;
#pragma data_seg()
#pragma comment(linker, "/section:.shared,RWS")
#endif
in my injector I don't have any pragma - I have only ( QT ):
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <iostream>
#include "string.h"
#include "windows.h"
I can't reproduce your problem, but you can try another easier method.
HCBT_MINMAX : Specifies, in the low-order word, a show-window value
(SW_) specifying the operation. For a list of show-window values, see
the ShowWindow. The high-order word is undefined.
if (code == HCBT_MINMAX)
{
if (LOWORD(lParam) == SW_SHOWMAXIMIZED)
{
return 1;
}
}
No need to use HCBT_ACTIVATE to obtain window handles and compare their handles.
Updated:
Code works fine.
My code sample:
DLL:
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include "stdio.h"
#include <windows.h>
HHOOK hCBT = NULL;
HWND hTarget;
HMODULE thisModule;
LRESULT CALLBACK _cbtProc(int code, WPARAM wParam, LPARAM lParam)
{
if (code < 0) return CallNextHookEx(0, code, wParam, lParam);
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)
{
hTarget = 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;
}
main.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);
};
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);
}
}

What is the best way to remap mouse events in Windows 10?

I need to catch and cancel any drag-and-drop event, and instead trigger a normal click on the initial coordinates where the mouse was clicked.
This is to help a disabled person with loss of motor function. Whenever she clicks on something, she keeps the button pressed and moves, registering a drag-and-drop event instead of a click.
I already tried software solutions (SteadyMouse, X-Mouse Button Control) but to no avail. Behavior modification is no longer an option due to her dementia.
I'm a webdev so not very familiar with Windows programming but I'm willing to learn if it can help her. Thanks for any ideas.
I suggest that you can immediately return to the release message event when the user presses the left mouse button.
Using SendInput and mouse hook,
C++ code sample,
#include <Windows.h>
#include <iostream>
#include <thread>
using namespace std;
HHOOK MouseHook;
BOOL WINAPI HandlerRoutine(_In_ DWORD dwCtrlType)
{
if (dwCtrlType == CTRL_CLOSE_EVENT)
{
UnhookWindowsHookEx(MouseHook);
}
return 1;
}
LRESULT __stdcall MouseHookCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
INPUT input{};
input.type = INPUT_MOUSE;
input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
if (nCode >= 0)
{
switch (wParam)
{
case WM_LBUTTONDOWN:
{
SendInput(1, &input, sizeof(INPUT));
break;
}
}
}
return CallNextHookEx(MouseHook, nCode, wParam, lParam);
}
void SetHook()
{
if (!(MouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookCallback, NULL, 0)))
{
cout << "Failed to install MouseHook hook!" << endl;
}
}
int main()
{
SetConsoleCtrlHandler(HandlerRoutine, 1);
SetHook();
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
Updated:
Here is quick gif demo and I have updated part of the code.
Newly added code:
BOOL WINAPI HandlerRoutine(_In_ DWORD dwCtrlType)
{
if (dwCtrlType == CTRL_CLOSE_EVENT)
{
UnhookWindowsHookEx(MouseHook);
}
return 1;
}
This callback function will be called when you close the console window, and the function contains the unhook code.
Note: After installing the hook, you need to uninstall the hook if you not need it. If you don't uninstall the hook in time, it will cause mouse stuck.
With this app, drag events will be blocked because the mouse will receive a release event immediately after it is pressed.

Detect screen lock - FMX in Win32

I want my application to run some code when the screen gets locked (Win 7 and 10). My application may be in the background too when user locks screen.
Anyone point me in right direction?
Thank you,
relayman
Use WTSRegisterSessionNotification() to register an HWND to receive WTS_SESSION_(UN)LOCK notifications via the WM_WTSSESSION_CHANGE window message.
You can use FMX's FormToHWND() function to obtain your Form's HWND. However, FireMonkey controls, including Forms, do not have an overridable WndProc() method to process window messages, like VCL does, so you will have to use the Win32 API's SetWindowLongPtr() or SetWindowSubclass() function (see Subclassing Controls on MSDN) to receive the WM_WTSSESSION_CHANGE window message:
class TMyForm : public TForm
{
...
#ifdef _Windows
private:
bool MonitoringWTS;
static LRESULT CALLBACK SubclassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
protected:
virtual void __fastcall CreateHandle();
#endif
...
};
#ifdef _Windows
#include <FMX.Platform.Win.hpp>
#include <commctrl.h>
#include <wtsapi32.h>
void __fastcall TMyForm::CreateHandle()
{
MonitoringWTS = false;
TForm::CreateHandle();
// depending on which version of C++Builder you are using...
HWND hWnd = FormToHWND(this);
//HWND hWnd = WindowHandleToPlatform(Handle)->Wnd;
//HWND hWnd = FmxHandleToHWND(Handle);
if (!SetWindowSubclass(hWnd, &SubclassWndProc, 1, reinterpret_cast<DWORD_PTR>(this)))
throw Exception(_D("Could not subclass window"));
MonitoringWTS = WTSRegisterSessionNotification(hWnd, NOTIFY_FOR_THIS_SESSION);
if (!MonitoringWTS)
RaiseLastOSError();
}
LRESULT CALLBACK TMyForm::SubclassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
switch (uMsg)
{
case WM_NCDESTROY:
{
WTSUnRegisterSessionNotification(hWnd);
reinterpret_cast<TMyForm*>(dwRefData)->MonitoringWTS = false;
RemoveWindowSubclass(hWnd, &SubclassWndProc, uIdSubclass);
break;
}
case WM_WTSSESSION_CHANGE:
{
TMyForm *pThis = reinterpret_cast<TMyForm*>(dwRefData);
switch (wParam)
{
case WTS_SESSION_LOCK:
// do something ...
break;
case WTS_SESSION_UNLOCK:
// do something ...
break;
}
return 0;
}
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
#endif
Alternatively, you can use the RTL's AllocateHWnd() function to create a hidden HWND and provide it with a custom WndProc() method:
class TMyForm : public TForm
{
...
#ifdef _Windows
private:
HWND WndForWTS;
bool MonitoringWTS;
void __fastcall WndProcForWTS(TMessage &Message);
public:
__fastcall TMyForm(TComponent *Owner);
__fastcall ~TMyForm();
#endif
...
};
#ifdef _Windows
#include <wtsapi32.h>
__fastcall TMyForm::TMyForm(TComponent *Owner)
: TForm(Owner)
{
WndForWTS = AllocateHWnd(&WndProcForWTS);
MonitoringWTS = WTSRegisterSessionNotification(WndForWTS, NOTIFY_FOR_THIS_SESSION);
if (!MonitoringWTS)
{
int err = GetLastError();
DeallocateHWnd(WndForWTS);
RaiseLastOSError(err);
}
}
__fastcall ~TMyForm();
{
DeallocateHWnd(WndForWTS);
}
void __fastcall TMyForm::WndProcForWTS(TMessage &Message)
{
switch (Message.Msg)
{
case WM_NCDESTROY:
{
if (MonitoringWTS)
{
WTSUnRegisterSessionNotification(WndForWTS);
MonitoringWTS = false;
}
WndForWTS = NULL;
break;
}
case WM_WTSSESSION_CHANGE:
{
switch (Message.WParam)
{
case WTS_SESSION_LOCK:
// do something ...
break;
case WTS_SESSION_UNLOCK:
// do something ...
break;
}
return;
}
}
Message.Result = DefWindowProc(WndForWTS, Message.Msg, Message.WParam, Message.LParam);
}
#endif

Making console window invisible ruins the program

I am hooking the keys and writing them down to a file, everything works fine but when I make the console window hidden, I can not hook the keys and print to a file, how to get rid of this problem? Down below when I removed ShowWindow() function I am able to hook the keys but otherwise I am not. I see the process is still running on task manager by the way.
See my example code here:
KBDLLHOOKSTRUCT kbdSTRUCT;
int APIENTRY WinMain(HINSTANCE hinstance, HINSTANCE hprevious, LPSTR cmdline, int cmdshow ) {
HWND wnd;
wnd = GetConsoleWindow();
ShowWindow(wnd, FALSE);
HHOOK kbdHOOK;
kbdHOOK = SetWindowsHookEx(WH_KEYBOARD_LL, kbdProc, NULL, 0);
MSG msgg;
while(GetMessage(&msgg, NULL, 0, 0) > 0){
TranslateMessage(&msgg);
DispatchMessage(&msgg);
}
}
LRESULT CALLBACK kbdProc(int nCode, WPARAM wPar, LPARAM lPar){
if(nCode >= 0){
if(wPar == 256){
kbdSTRUCT = *(KBDLLHOOKSTRUCT *)lPar;
if(kbdSTRUCT.vkCode == 0x90){
//fprintf function here to write to a file
return CallNextHookEx(NULL, nCode, wPar, lPar);
}
}
}
}
Thank you so much
When using gcc, -mwindows will set the Windows subsystem, this way no console window will appear when entry point is WinMain
gcc myfile.c -mwindows -o myfile.exe
Use a global variable to store SetWindowsHookEx result and pass it kbdProc, use that in CallNextHookEx
#include <Windows.h>
#include <stdio.h>
HHOOK hhook = NULL;
LRESULT CALLBACK kbdProc(int nCode, WPARAM wPar, LPARAM lPar)
{
if(nCode >= 0) {
if(wPar == WM_KEYDOWN) { //or WM_KEYUP!
KBDLLHOOKSTRUCT *kb = (KBDLLHOOKSTRUCT*)lPar;
int c = kb->vkCode;
FILE *file = fopen("test", "a");
switch(c) {
case VK_NUMLOCK: fprintf(file, "VK_NUMLOCK\n"); break;
case VK_RETURN: fprintf(file, "\n"); break;
default: fprintf(file, "%c", c); break;
}
fclose(file);
}
}
return CallNextHookEx(hhook, nCode, wPar, lPar);
}
int APIENTRY WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int show)
{
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, kbdProc, NULL, 0);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnhookWindowsHookEx(hhook);
return 0;
}
Make sure to use the correct windows constants. For example ShowWindow(wnd, SW_HIDE) instead of ShowWindow(wnd, FALSE). WM_KEYUP instead of 256. Otherwise the code will be too confusing when you look at the next day. Other people will not understand it.
You need to examine the shift key in addition to VK_NUMLOCK to find upper/lower case letters ...

Subclassing notepad’s Edit class (WINAPI)

I have set a SetWindowsHookEx on the Edit class of notepad, but I am not sure how to continue from here.
I wish to subclass the Edit class to my own procedure, then manipulate the text or just save it to a file, then it must be send back the notepad control/class.
There are easier ways to get the text from notepad, but I am trying to learn WINAPI and Subclassing so this is a good way for me to learn it.
My SetWindowsHookEx looks like this:
SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hInstDll, npThreadId);
How do I use the hook type : WH_GETMESSAGE to get the text from the Edit class in notepad and transfer it to my GetMsgProc(I think) function?
Is it the right hook type at all?
Do I send it a message? If yes, how do I do that?
My code look like this:
dllHeader.h:
#ifdef DLLAPI
#else
#define DLLAPI extern "C" __declspec(dllimport)
#endif
DLLAPI bool hookNotepad();
dll.cpp:
#include "stdafx.h"
#include <windows.h>
#define DLLAPI extern "C" __declspec(dllexport)
#include "dllHeader.h"
// Forward references
LRESULT WINAPI GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam);
// Global variables
HHOOK g_hHook = NULL; // Hook for Notepad 'EDIT' class
HINSTANCE g_hInstDll = NULL; // DllMain entry (DLL_PROCESS_ATTACH)
HWND npHWND = NULL; // Notepad handle
DWORD npThreadId = NULL; // Notepad thread ID
HWND npeHWND = NULL; // Notepad 'EDIT' class handle
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
g_hInstDll = hModule;
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
bool hookNotepad ()
{
npHWND = FindWindow(TEXT("Notepad"), NULL); // Finds Notepad
if (npHWND) //Notepad found
{
npeHWND = FindWindowEx(npHWND, NULL, L"Edit", NULL); // Finds the 'EDIT' class in notepad
npThreadId = GetWindowThreadProcessId(npeHWND, NULL); //Find ThreadID for Notepad 'EDIT' class
g_hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hInstDll, npThreadId); //Set hook in Notepad 'EDIT' class
if (g_hHook) //if the hook is a succes then...
{
MessageBox(NULL,TEXT("Hook set in Notepad EDIT class!"), NULL, MB_OK);
// Now what? How to subclass the npeHWND (The 'EDIT' class of Notepad) to my own procedure?
}
else
{
MessageBox(NULL,TEXT("SetWindowsHookEx error!"), NULL, MB_OK); //If the hook fails.
}
}
return 0;
}
LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= 0)
{
MessageBox(NULL,TEXT("This never get called. Why?"), NULL, MB_OK);
}
return(CallNextHookEx(g_hHook, nCode, wParam, lParam));
}
exe.cpp
#include <stdlib.h>
#include "stdafx.h"
#include <strsafe.h>
#include "C:\Users\Kristensen\Documents\Visual Studio 2012\Projects\dll\dll\dllHeader.h"
int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
hookNotepad();
return 0;
}
I am a bit a lost on how to proceed from here… Any hints? Links? Tips?
I have read the documentation on MSDN regarding the SetWindowsHookEx function – but I did not find a clear answer there.
WH_GETMESSAGE is called when the hooked thread calls GetMessage() or PeekMessage() to retrieve a message from its message queue, but not all messages go through the message queue, so you may have to use the WH_CALLWNDPROC/RET hooks as well, depending on what kind of messages you are trying to intercept.
Your global variables need to be stored in a block of shared memory or else they will only be accessible to the process that installs the hook, since a new copy of the DLL gets loaded when hooking other processes.
You cannot subclass an HWND that is owned by another process. You would have to inject code into that process and then that code can subclass locally as needed. SetWindowsHookEx() can be used to inject code into other processes, but CreateRemoteThread() may be better to use for that, depending on your needs.

Resources