Set WH_GETMESSAGE hook makes the system dead - windows

I use SetWindowsHookEx to install a global GETMESSAGE hook in a dll like this:
SetWindowsHookEx(WH_GETMESSAGE,HookProc,hModule,0);
and the the hook procedure within the dll too.But when i called InstallHook(this function is exported from the DLL) to install the GETMESSAGE hook,booom, the system can not respon the mouse operation,the windows on the desktop can be close or move) ,here is my HookProc Code:
LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode < 0)
{
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
WCHAR szMsg[MAX_PATH] = { 0 };
PMSG pMsg = (PMSG)lParam;
wsprintf(szMsg, L"MSG_FROM:%08x,MSG_TYPE:%d", pMsg->hwnd,pMsg->message);
OutputDebugString(szMsg);
return CallNextHookEx(NULL,nCode, wParam, lParam);
}
I've read the MSDN for many times,it just said i must process the message if the ncode is HC_ACTION,but,i don't know how to process the message.I think there must be someone else has this problem too, so, hope somebody give some help, and tell me how you process this trouble.
Thanks a lot.

Related

How to pass arguments to SetWindowsHookEx's callback? (if even possible)

I'm using SetWindowsHookEx with WH_CALLWNDPROC to catch all WndProc messages - and it works fine.
I was wondering if there is a way to store a parameter somewhere where the callback function can read and use it.
I assume that because the callback function is inside the "other" process, there's no connection to the process calling the SetWindowsHookEx, so just storing a value in a static variable wont do any good..
For example:
void Hook(DWORD dwThread, int randomNumber)
{
MagicallyStore(randomNumber);
SetWindowsHookEx(WH_CALLWNDPROC, hookProc, GetModuleHandle(L"WNDProcHooks"), dwThread);
...
...
}
LRESULT CALLBACK hookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
int randomNumber = MagicallyRestore();
DoSomthing(randomNumber);
return CallNextHookEx(0, nCode, wParam, lParam);
}
I already thought about having the "MagicallyStore" function write the parameter to a file and reading it once in the "MagicallyRestore" function - but there must be a better way..
Thanks in advance :)

How to read the data from lParam (the pointers value)

I made a small application that sends text to notepad via SendMessage and EM_REPLACESEL.
Now I’m trying to hook notepad to get the EM_REPLACESEL value (the lParam value and in this case the “GET THIS TEXT” text).
EDIT: See this picture: http://i.stack.imgur.com/8scNL.jpg
The hook works fine, my problem is to listen for the EM_REPLACESEL message and grab the value from the lParam.
This code works fine, when messages are sent to notepad:
LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
Beep (2000,100);
return(CallNextHookEx(g_hHook, nCode, wParam, lParam));
}
So now I want to intercept EM_REPLACESEL messages. This do not work:
LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == EM_REPLACESEL)
{
Beep (2000,100);
}
return(CallNextHookEx(g_hHook, nCode, wParam, lParam));
}
1) How to listen for the EM_REPLACESEL message?
2) When I have gotten the message how to grab the lParam value and e.g. show it in a MessageBox. Something like this:
LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == EM_REPLACESEL)
{
MSG *lpMsg;
lpMsg = (MSG *) lParam;
MessageBox(NULL,(LPCWSTR)lpMsg,NULL,NULL);
}
return(CallNextHookEx(g_hHook, nCode, wParam, lParam));
}
Thanks
EM_REPLACESEL is a sent message, not a posted message, so you need to use a WH_CALLWNDPROC hook instead of a WH_GETMESSAGE hook, eg:
LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HC_ACTION) {
CWPSTRUCT* cwps = (CWPSTRUCT*)lParam;
if (cwps->message == EM_REPLACESEL) {
Beep (2000,100);
// etc..
}
}
return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}
... = SetWindowsHookEx(WH_CALLWNDPROC, CallWndProc, ...),
Your GetMsgProc() callback is coded wrong. Carefully read the linked MSDN page to see what the arguments of the callback mean. The nCode argument is not the message number, it specifies whether or not you should process the message. You want to use the passed lParam to recover the message that you intercepted. Make it look similar to this instead:
LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HC_ACTION) {
MSG* pmsg = (MSG*)lParam;
if (pmsg->message == WM_LBUTTONDOWN) {
Beep (2000,100);
// etc..
}
}
return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}
Do note that you appear to use the WH_GETMESSAGE hook. It only works for messages that are posted to the message queue with PostMessage(). But EM_REPLACESEL is a message that's sent with SendMessage(). That requires a different hook, WH_CALLWNDPROC or WH_CALLWNDPROCRET.
This is how I normally do it.
LRESULT CALLBACK GetMsgProc(MSG nCode, WPARAM wParam, LPARAM lParam)
{
while(GetMessage(&nCode, NULL, 0, 0) > 0)
{
if(nCode.message == EM_REPLACESEL)
{
//Do something
}
else
DispatchMessage(&nCode);
}
return 0;
}

How to use DialogBox in Windows API

I'm learning windows api for some weeks, now I got a problem, my code is like this
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
switch(message){
case(...)
DialogBox(hInstance,MAKEINTRESOURCE(IDD_MYDIALOG),hwnd,(DLGPROC)MyDialogProc);
return 0;
}
bool MyDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
switch (message){
...
}
return false;
}
I don't know what else should I do before I use DialogBox where should I place EndDialog(). IDD_MYDIALOG is a resource file created by myself. I don't understand what is hInstance and how to get it, I think I just need a simple example, than I can know how use DialogBox. Thank you for helping!

SetWindowsHookEx HCBT_CREATEWND GetWindowText

Anyboby knows how to get text of a created window? I set hook on CreateWindow, but GetWindowText returns empty string.
hCBTHook = SetWindowsHookEx(WH_CBT, (HOOKPROC) &CBTHook, g_appInstance, 0);
LRESULT CALLBACK CBTHook(int nCode, WPARAM wParam, LPARAM lParam)
{
if(nCode == HCBT_CREATEWND)
{
HWND hwnd = (HWND)wParam;
CHAR buf[256];
GetWindowText(hwnd, buf, 256);
}
return CallNextHookEx(hCBTHook, nCode, wParam, lParam);
}
"The system calls the hook procedure before sending the WM_CREATE or WM_NCCREATE message to the window."
The window may not have text yet, your callback is invoked very early in the process of window creation. The name of the window gets passed in as part of the CREATESTRUCT message sent with WM_CREATE which would be the earliest the window could do something about having text. Even to hard code something, it would have to be in WM_NCCREATE, which still hasn't happened yet when your callback is called.
However, the callback itself also gets passed the the CREATESTRUCT. If the name that was passed to CreateWindow is what you are after, that's available to you as well.

WM_MOUSEHOVER in a global hook

I have implemented custom tooltips for a couple of controls in my application (MFC) but I would like to make it general for all the controls.
Right now I am calling TrackMouseEvent in WM_MOUSEMOVE and then catching WM_MOUSEHOVER (both in the overwritten function WindowProc of the control). But this way I have to duplicate code for every control. So my intention was to set a global hook for mouse events and there ask the control for the message to display in the tooltip.
The problem is that I am not able to catch WM_MOUSEHOVER in a global hook. This is the code:
hMouseHook = SetWindowsHookEx( WH_MOUSE,
CallWndMouseProc,
NULL,
AfxGetThread()->m_nThreadID);
hMainHook = SetWindowsHookEx( WH_CALLWNDPROC,
CallWndProc,
NULL,
AfxGetThread()->m_nThreadID);
LRESULT CALLBACK CallWndMouseProc( int nCode,
WPARAM wParam,
LPARAM lParam )
{
if(nCode == HC_ACTION)
{
MOUSEHOOKSTRUCT* pwp = (MOUSEHOOKSTRUCT*)lParam;
TRACE( _T("message: %x hwnd: %x x: %d y: %d\n"),
wParam,
pwp->hwnd,
pwp->pt.x,
pwp->pt.y);
TRACKMOUSEEVENT eventTrack;
eventTrack.cbSize = sizeof(TRACKMOUSEEVENT);
eventTrack.dwFlags = TME_HOVER;
eventTrack.dwHoverTime = HOVER_DEFAULT;
eventTrack.hwndTrack = pwp->hwnd;
_TrackMouseEvent(&eventTrack);
if(wParam == WM_MOUSEHOVER)
{
AfxMessageBox(_T("CallWndMouseProc: WM_MOUSEHOVER"));
}
}
// let the messages through to the next hook
return CallNextHookEx( hMouseHook,
nCode,
wParam,
lParam);
}
LRESULT CALLBACK CallWndProc( int nCode,
WPARAM wParam,
LPARAM lParam )
{
if(nCode == HC_ACTION)
{
CWPSTRUCT *pData = (CWPSTRUCT*)lParam;
if(pData->message == WM_MOUSEHOVER)
{
AfxMessageBox(_T("CallWndProc: WM_MOUSEHOVER"));
}
}
// let the messages through to the next hook
return CallNextHookEx( hMainHook,
nCode,
wParam,
lParam);
}
Both hooks are being call for the rest of messages and I am sure WM_MOUSEHOVER is being sent because it's capture in the WindowProc function. For instance this is the WindowProc function for a custom CListBox:
LRESULT CMyListBox::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
if(message == WM_MOUSEHOVER)
{
AfxMessageBox(_T("WindowProc: WM_MOUSEHOVER"));
}
return CListBox::WindowProc(message, wParam, lParam);
}
Ok. So what I am missing? It's just not possible to capture this message in a global hook? Is there other way to make this without having to put the same code in every single control?
Thanks.
Javier
WM_MOUSEHOVER is posted to the thread's message queue, so you won't see it with WH_CALLWNDPROC (that's for sent messages). WH_MOUSE does get posted messages, so I find it a little strange that you aren't seeing it... Perhaps the hook only gets low level mouse input messages? Try a WH_GETMESSAGE hook.

Resources