WH_GETMESSAGE global hook not working - c

I am trying to set a global GetMessage hook on all threads. This is my DLL:
#include <windows.h>
__declspec(dllexport) LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
MessageBeep(0);
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
As you can see, it's not much. I just want it to call MessageBeep whenever it's called.
#include <windows.h>
typedef LRESULT (CALLBACK *LPGetMsgProc)(int nCode, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nCmdShow)
{
if(!(HMODULE hDll = LoadLibrary("library.dll")))
return 1;
if(!(LPGetMsgProc pfnProc = (LPGetMsgProc)GetProcAddress(hDll, "GetMsgProc#12")))
return 2;
HHOOK hMsgHook = SetWindowsHookEx(WH_GETMESSAGE, pfnProc, hInstance, 0);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0) > 0) {}
UnhookWindowsHookEx(hMsgHook);
return 0;
}
My WinMain loads the library, gets the procedure and sets the hook. However, MessageBeep is never being called. Is there something I'm doing wrong here?
Also, one other thing has been bothering me. In this call:
if(!(LPGetMsgProc pfnProc = (LPGetMsgProc)GetProcAddress(hDll, "GetMsgProc#12")))
I was forced to use "GetMsgProc#12" because I couldn't get it right any other way. Can somebody please tell me how I'm supposed to use a .def file or something else so I can just have it as "GetMsgProc"? Though MSDN stated that since I have __declspec(dllexport) in my declaration I wouldn't need it...
My IDE is Code::Blocks with MinGW. Thanks in advance.

The third parameter...
HHOOK hMsgHook = SetWindowsHookEx(WH_GETMESSAGE, pfnProc, hInstance, 0);
...is the handle passed into your WinMain function. But it needs to refer to the DLL where the callback function resides - in your case, that'd be hDLL.

Related

Why does CreateWindow in 64-bit Visual Studio C destroy itself on creation?

I have some example code that simply puts a window on the screen in Windows 10. The program runs fine under 32 bit: the window call back procedure gets sent messages in the creation of the window.
Under 32-bit, the first three messages are:
WM_GETMINMAXINFO
WM_NCCREATE
WM_NCCALCSIZE
and it proceeds from there until the window is built.
However, under 64-bit, this does not happen; instead, these are the messages sent:
WM_GETMINMAXINFO
WM_NCCREATE
WM_NCDESTROY
As you can see, right after the window is created, the OS sends a message to destroy it!
Here's the actual code:
/*****************************************************************************/
/* This sample demonstrates how to continuously acquire pictures */
#include <windows.h>
#include <stdio.h>
#define _NIWIN
#define PB_QUIT 101 /* id for quit application push button */
// Window proc
LRESULT CALLBACK ImaqSmplProc(HWND hWnd, UINT iMessage, UINT wParam, LONG lParam);
// windows GUI globals
static HINSTANCE hInst;
static HWND ImaqSmplHwnd;
static HWND HStop, HGrab, HQuit, HIntfName, HFrameRate;
static long CanvasWidth = 512; // width of the display area
static long CanvasHeight = 384; // height of the display area
static long CanvasTop = 10; // top of the display area
static long CanvasLeft = 10; // left of the display area
static long AcqWinWidth;
static long AcqWinHeight;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
CHAR ImaqSmplClassName[] = "Imaq Sample";
WNDCLASS ImaqSmplClass;
MSG msg;
// register the main window
hInst = hInstance;
if (!hPrevInstance)
{
ImaqSmplClass.style = CS_HREDRAW | CS_VREDRAW;
ImaqSmplClass.lpfnWndProc = (WNDPROC) ImaqSmplProc;
ImaqSmplClass.cbClsExtra = 0;
ImaqSmplClass.cbWndExtra = 0;
ImaqSmplClass.hInstance = hInstance;
ImaqSmplClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
ImaqSmplClass.hCursor = LoadCursor (NULL, IDC_ARROW);
ImaqSmplClass.hbrBackground = GetStockObject(LTGRAY_BRUSH);
ImaqSmplClass.lpszMenuName = 0;
ImaqSmplClass.lpszClassName = ImaqSmplClassName;
if (!RegisterClass (&ImaqSmplClass))
return (0);
}
// creates the main window
ImaqSmplHwnd = CreateWindow(ImaqSmplClassName, "LLGrab", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, 680, 440, NULL, NULL, hInstance, NULL);
// creates the quit application button
if (!(HQuit = CreateWindow("Button","Quit",BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE,
550,152,80,40,ImaqSmplHwnd,(HMENU)PB_QUIT,hInstance,NULL)))
return(FALSE);
// Display the main window
ShowWindow(ImaqSmplHwnd, SW_SHOW);
UpdateWindow(ImaqSmplHwnd);
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return (int)(msg.wParam);
}
// Message proc
LRESULT CALLBACK ImaqSmplProc(HWND hWnd, UINT iMessage, UINT wParam, LONG lParam)
{
WORD wmId;
LRESULT theResult;
switch (iMessage)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
switch (wmId)
{
case PB_QUIT:
PostQuitMessage(0);
break;
}
break;
case WM_NCDESTROY:
break;
case WM_DESTROY:
PostQuitMessage(0);
default:
theResult = DefWindowProc(hWnd, iMessage, wParam, lParam);
return theResult;
break;
}
return 0;
}
Your ImaqSmplProc() window procedure is declared incorrectly, causing you to pass bad data to DefWindowProc().
For WM_NCCREATE, the lParam holds a pointer, which you are truncating under 64bit to a 32bit value, so DefWindowProc() fails to process WM_NCCREATE correctly, which then causes CreateWindow() to destroy the window. If you debug the code, you will likely see DefWindowProc() returning FALSE when processing WM_NCCREATE with a bad lParam value.
If an application processes this message, it should return TRUE to continue creation of the window. If the application returns FALSE, the CreateWindow or CreateWindowEx function will return a NULL handle.
To fix this, the wParam and lParam parameters MUST be declared as WPARAM and LPARAM, respectively:
LRESULT CALLBACK ImaqSmplProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
This matches the actual signature of WNDPROC:
LRESULT CALLBACK WindowProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
WPARAM and LPARAM are declared as UINT_PTR and LONG_PTR, respectively. Which means they are pointer-sized integers, and so have different sizes under 32bit and 64bit. Whereas UINT and LONG have the same size on both 32bit and 64bit. See Windows Data Types. Your original code is not accounting for this difference.
You used a type-cast to silence the compiler from alerting you to your incorrect declaration. You need to get rid of the type-cast when assigning ImaqSmplProc to ImaqSmplClass.lpfnWndProc:
ImaqSmplClass.lpfnWndProc = ImaqSmplProc;
Any time you find yourself using a type-cast, question yourself as to why, you may be doing something wrong. Don't use a type-cast unless you absolutely need it. Don't use a type-cast just to keep the compiler silent, it complains about questionable/erroneous things for a reason.
The problem is in the types you have specified for the wParam and lParam arguments to your ImaqSmplProc function. These should be of types WPARAM and LPARAM, respectively.
Why? These are defined as UINT_PTR and LONG_PTR types - which are 64-bit integers on x64 builds; thus, your specified UINT and LONG types are the wrong sizes, so you have undefined behaviour (at best).
Change the definition/declaration to:
LRESULT CALLBACK ImaqSmplProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)

When I run code written using the Windows api, it turns off as soon as it is turned on (in Visual Studio)

I wrote this code using a windows api (a program that pops up a messagebox when I left-click) and when I run it, it seems to turn off as soon as it's turned on. )
(run with f5)
I think it's end, but I don't know what's wrong. Is it a code problem?
I use visual studio.
LRESULT CALLBACK MouseHookProc(_In_ int nCode,
_In_ WPARAM wParam,
_In_ LPARAM lParam)
{
switch (wParam) {
case WM_LBUTTONDOWN:
MessageBoxA(0, "hi", "hanu", 0);
}
return CallNextHookEx(g_Hook, nCode, wParam, lParam);
}
int APIENTRY WinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nShowCmd)
{
HHOOK mouseHook = SetWindowsHookEx(WH_MOUSE_LL,MouseHookProc, hInstance, NULL);
}
Please point out if the question lacks information
You need:
a program that doesn't exit immediately because its main function returns
a message loop
The two condition are easily met by adding below code just after the SetWindowsHookEx call:
MSG msg;
while ( GetMessage( &msg, NULL, 0, 0 ) );
Have fun with the multiple Dialog Boxes you'll get!

Use WH_MOUSE globally without DLL

I have a code to display a part of screen when mouse moves. But the WH_MOUSE doesn't work. I need to change GetModuleHandle(0), 0 to hInst, GetCurrentThreadId().
But then the application will work only when the mouse is over the application itself.
I want it global and I tried WH_MOUSE_LL, it is slower then WH_MOUSE.
Is that possible to use WH_MOUSE globally without DLL?
void SetHook()
{
gMouseHook = SetWindowsHookEx(WH_MOUSE, MouseProc, GetModuleHandle(0), 0);
}
//================================================================================
// Mouse Hook
static LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode < 0) {
return CallNextHookEx(gMouseHook, nCode, wParam, lParam);
}
if (wParam == WM_MOUSEMOVE) {
MOUSEHOOKSTRUCT *mouseInfo = (MOUSEHOOKSTRUCT*)lParam;
int x = mouseInfo->pt.x;
int y = mouseInfo->pt.y;
PrintScreen(x, y);
}
return CallNextHookEx(gMouseHook, nCode, wParam, lParam);
}
Is that possible to use WH_MOUSE globally without DLL?
No, the hook procedure needs to be in a DLL so that it can be injected into other processes.
I tried WH_MOUSE_LL, it is slower then WH_MOUSE.
That probably means your hook procedure is slow.

prohibit to move window with some title

I need to prohibit window moving with some title.
// Hooks.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
extern "C" __declspec(dllexport) TCHAR s[50];
extern "C" __declspec(dllexport) HHOOK hHook;
extern "C" __declspec(dllexport) LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam);
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
return 1;
}
TCHAR s[50];
HHOOK hHook;
LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
// HDC hdc;
if (nCode < 0)
return CallNextHookEx(hHook, nCode, wParam, lParam);
// hdc = GetDC(hWnd);
CBT_CREATEWND* cbt=(CBT_CREATEWND*)lParam;
if (nCode==HCBT_MOVESIZE)
if (!lstrcmp(s,cbt->lpcs->lpszName)) return 1;
return CallNextHookEx(hHook, nCode, wParam, lParam);
return 0;
}
but I've got an error when I move window. When I change its position It changes but then I've got error - access violation at adress 67471040 in module Hooks.dll(my dll).Read of adress 00000116
You are casting lParam into a pointer to CBT_CREATEWND, but that is only so if nCode==HCBT_CREATEWND, and that is obviously not the case. When nCode==HCBT_MOVESIZE then lParam points to a RECT struct.
You should process first the HCBT_CREATEWND, filter it and save the related HWND to make the condition when HCBT_MOVESIZE happens.
That won't work if the window changes the title, however.
BTW, can't you just call GetWindowText() to get the window title?

How can I access a variable in a calling application from a dll?

I'm trying a little concept test to change one of the features of the logitech MS3200 keyboard (the zoom feature). I've got the keys that are sent from the zoom control. So, I have a main app, and a dll that contains a hook procedure.
Here's the main app:
#include <stdio.h>
#include <windows.h>
HANDLE hHook;
int main()
{
HINSTANCE hMod = GetModuleHandle(NULL);
hHook = SetWindowsHookEx(WH_KEYBOARD, HookProc,0,0);
if(hHook == NULL)
printf("Unable to set hook! Error: %d", GetLastError());
else
printf("Hook set successfully!");
while(TRUE)
{
Sleep(1000);
}
return 0;
}
And here is the hook procedure dll:
#include <windows.h>
int __declspec (dllexport) HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if(nCode < 0)
{
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
if(wParam == VK_ADD || wParam == VK_SUBTRACT)
{
short status = GetKeyState(VK_CONTROL);
if(status == 1)
{
if(wParam == VK_ADD)
wParam = VK_UP;
else
wParam = VK_DOWN;
}
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
int WINAPI dllmain(HINSTANCE hMod, DWORD data, LPVOID lpVOid)
{
return 0;
}
I need to be able to access what's returned by SetWindowsHookEx (hHook) from the dll, in order to call CallNextHookEx().
It's probably possible, but it's not worth your time to investigate.
Instead, move the hook setting code to the DLL.
Oh, and I think you need to pass the DLL module handle to the hook setting function, not a NULL
One possible way to handle this would be to have another exported function in your DLL to pass the hHook to, and save that in a variable local within the DLL for use in the HookProc.
HANDLE dllHook;
void __declspec (dllexport) HookHandle(HANDLE hHook)
{
dllHook = hHook;
}
int __declspec (dllexport) HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if(nCode < 0 && dllHook!= NULL)
{
return CallNextHookEx(dllHook, nCode, wParam, lParam);
}
//....
}
int WINAPI dllmain(HINSTANCE hMod, DWORD data, LPVOID lpVOid)
{
dllHook = NULL; //initialize
return 0;
}
Code in a DLL can't directly access variables in the calling app, because there's no guarantee that the app that loads the DLL will have those variables defined, and even if it did, the DLL has no way to know where it would be stored.
You could have a global variable in the DLL and an extra entry point to set it, which you call after calling SetWindowsHookEx. The DLL would need to wait until this entry point is called before calling CallNextHookEx.
On NT/XP/2003 etc the first param to CallNextHookEx is ignored. See the documentation for CallNextHookEx:
http://msdn.microsoft.com/en-us/library/ms644974%28VS.85%29.aspx
hth

Resources