I want to set global hook that tracks which application is active.
In my main program I am doing the foloowing :
HMODULE mod=::GetModuleHandle(L"HookProcDll");
HHOOK rslt=(WH_CALLWNDPROCRET,MyCallWndRetProc,mod,0);
The hook procedure which is called MyCallWndRetProc exists in separate dll called HookProcDll.dll. The hook procedure is watching for WM_ACTIVATE message.
The thing is that the code stucks in the line where I am setting the hook, i.e in the line where I am calling ::SetWindowsHookEx. And then Windows gets unresponsive, my task bar disappears and I am left with empty desktop. Then I must reset the computer.
What am doing wrong, why Windows get unresponsive ? and
Do I need to inject HookProcDll.dll in every process in order to set the global hook, and how can I do that ?
This almost definitely sounds like a crashing bug in MyCallWndRetProc. You specify your hook DLL to get loaded in every process with a window and it crashes when MyCallWndRetProc gets called after a window message. Since it gets called after every window message in every process, it'll eventually take down every process displaying UI in the user session. You can't even launch new apps since your hook proc will be immediately loaded into them.
Including the code to MyCallWndRetProc, and perhaps your DllMain as well, should give us some insight into what is happening.
This is the code for my hook procedure, and it is stored in HookProcDll.dll :
#include "HookProcDll.h"
LRESULT CALLBACK MyCallWndRetProc(
__in int nCode,
__in WPARAM wParam, /* whether the msg is sent by the current process */
__in LPARAM lParam /* pointer to CWPRETSTRUCT , which specifies details about the message */
)
{
if(nCode >=0)
{
CWPRETSTRUCT* retStruct=(CWPRETSTRUCT*)lParam;
if(retStruct->message == WM_ACTIVATE)
{
}
}
return ::CallNextHookEx(0,nCode,wParam,lParam);
}
My HookProcDll.dll has no explicit DllMain function .The HookProcDll.dll is made with visual studio dll project so I guess it includes standrad implementation for DllMain.
Related
I am setting a global hook with the following code:
SetWindowsHookEx(WH_MOUSE_LL, MouseProc, NULL, 0)
I have a breakpoint set so that when I first run the application I can see that the MouseProc method is called. This works but after the first time it is no longer called. Is the Hook automatically removed, how do I get this so that the hook automatically persists? I am writing this application for windows and this is a C++ win32 project.
I have a breakpoint set
That's enough to explain the problem. The debugger will break of course. Which prevents further mouse messages from being delivered to the window with the focus. Windows puts up with that for 5 seconds, then unceremoniously disables your hook because it thinks your code is broken.
The timeout is configurable, you can use Regedit.exe to set the HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout value. Not present by default, add the DWORD value first. The unit is milliseconds.
First you need to do:
return CallNextHookEx(_hook, nCode, wParam, lParam);
in your MouseProc, so it should return.
Second, it's not possible to debug most of codes which does have hook, your app will crash, because windows expecting your MouseProc function to return as soon as possible with return.
Also your code should have Message handling code, like GetMessage, TranslateMessage and DispatchMessage.
Example code: SetWindowsHookEx for WH_MOUSE
I want to disallow the user of my application from using alt-tab. I'm trying to solve this by using a low level keyboard hook.
Setting it up works perfectly, the callback procedure is triggered when I press the key combination etc. The weird thing that happens is that I can alt-tab out of the application but then alt-tabbing is disabled, completely. I switch applications with the mouse and try alt-tabbing but nothing happens. I switch back to my application and alt-tab again and it switches the application, but only one step. When out of my application the alt-tab isn't working anymore.
I've tried different scenarios, first I thought it had something to do with the debugger in VS2010 but no, running it with out the debugger gives the same results.
Have I completely misunderstood this hook procedure, is it meant to only catch stuff happening when the application isn't in focus?
osman.hpp :
static HHOOK m_hhook;
static LRESULT CALLBACK lowLevelKeyboardProc( int key, WPARAM wParam, LPARAM lParam );
osman.cpp :
HHOOK OSMan::m_hhook;
/*
* pseudo init code
*/
void OSMan::init()
{
m_hHook = SetWindowsHookEx( WH_KEYBOARD_LL, (HOOKPROC)lowLevelKeyboardProc, 0, 0 );
}
LRESULT CALLBACK OSMan::lowLevelKeyboardProc( int key, WPARAM wParam, LPARAM lParam )
{
KBDLLHOOKSTRUCT *pkbhs = (KBDLLHOOKSTRUCT *) lParam;
switch (key)
{
case HC_ACTION:
{
if (pkbhs->vkCode == VK_TAB && pkbhs->flags & LLKHF_ALTDOWN)
return 1;
}
default:
break;
}
return CallNextHookEx( m_hHook, key, wParam, lParam);
}
edit:
added code.
If you want to disable alt+tab correctly, you should just register the hotkey via RegisterHotKey(0,0,MOD_ALT,VK_TAB); and then handle (well, more ignore) the message that this generates, this allows you to make it application local, not worry about Windows hook chains and allows you to easily enable or disable it on the fly.
Although for a game, the idTech 4 input handling code has a vast array of the input gems.
You are installing a System Wide hook, that is why you have disabled the use of Alt-TAB on the whole system.
You can't use a WH_KEYBOARD_LL you must use a WH_KEYBOARD hook, and make it process specific.
The params of the SetWindowsHookEx will change if you make your hook process specific.
Here is an overview of the params :
dwThreadId [in]
Type: DWORD
The identifier of the thread with which the hook procedure is to be associated.
If this parameter is zero, the hook procedure is associated with all existing threads running in the same desktop as the calling thread.
PS : in reply to comment :
The hook only is installed after the process got one appropriate event. While hooking onto keyboard messages, you will have to send at least one keyboard message before the hook is installed.
Work Around
Maybe you want to work around this issue by using the ShowWindow function ?
Here is the doc : http://www.pinvoke.net/default.aspx/user32.showwindow
cf : http://www.codeproject.com/Articles/4610/Three-Ways-to-Inject-Your-Code-into-Another-Proces
cf http://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx
and
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644959(v=vs.85).aspx#wh_keyboardhook
I have an MFC application (using a legacy library that I can't change). When the application starts, it loads a couple of drivers and shows message boxes if some drivers couldn't be loaded. The loading of the drivers and the showing of the message boxes is done by a method inside the library that can't be changed (let's call this method Init). I would like to disable those message boxes (preventing them from "popping"). Is there something I could call before calling Init to disable Message Boxes temporarily and then re-enable them after?
(Note that if it is impossible to re-enable them after, I can very well live with that, I mostly want to disable them)
Thanks to all,
Note: If someone wonders about why I would like to do that, it is because my application exposes a COM interface and will be used by other applications. The only reason it is an application is that the library I use is much more easy to use when creating an MFC application (and not a dll). When it is called by my other applications, I don't want the message boxes to show, I just want to get the errors if something goes wrong.
I am not sure whether this could work. I use it for subclassing some messageboxes not to preven them to popup and they are not from a dll.
I set a hook to capture message boxes before poping up:
HHOK hMessageBoxHook_ = SetWindowsHookEx(WH_CBT,
&CbtHookProc,
::GetModuleHandle(NULL),
GetCurrentThreadId());
The new hook procedure (CbtHookProc) would be like this:
LRESULT CALLBACK CbtHookProc( int nCode,
WPARAM wParam,
LPARAM lParam)
{
if(nCode < 0)
{
return ::CallNextHookEx( hMessageBoxHook_,
nCode,
wParam,
lParam);
}
switch(nCode)
{
case HCBT_CREATEWND: // a window is about to be created
return -1;
}
return ::CallNextHookEx( hMessageBoxHook_,
nCode,
wParam,
lParam);
}
From microsoft documentation for HCBT_CREATEWND:
If the hook procedure returns a
nonzero value, the system destroys the
window
Then after calling Init you can remove the hook and message boxes will pop up again:
::UnhookWindowsHookEx(hMessageBoxHook_);
hMessageBoxHook_ = 0;
As I told you I can't assure it works but give it a try.
One way to do this would be to hook/unhook the calls to MessageBox/MessageBoxEx/etc. and just do nothing when these calls are made. Check this guide for details on hooking API calls. In your case, I would specifically look at Import Address Table method, which is quite easy to implement and allows you to achieve the functionality you want.
You may also want to check Microsoft's own Detours library, but I'm not sure on whether it supports replacing API calls functionality.
Hope it helps.
I had the same problem when using ODBC with MFC. Everytime there was an error, a message box would pop up showing the error, which was fine if I wanted one.
However, if I didn't, I only needed to surround it with:
TRY
{
// Call error-prone method
}
CATCH ( CException, pEx )
{
// Free resources
}
END_CATCH
The message box comes from the framework not knowing how to handle the exception. Simply catch it and do as you wish with it.
I have a ATLCOM Shell Extension which adds Right Click Extension to Windows Explorer. How Can I pass a message from my DLL to another MFC application.
To Sumarize, I want to pass a Message from DLL to MFC application.
You can use Windows API SendMessage or PostMessage.
Have you tried using Windows messages?
You can define you own custom messages like this:
const UINT WM_YOUR_CUSTOM_MESSAGE = ::RegisterWindowMessage(_T("Your_custom_message"));
You receive the message in a standard WindowProc() function:
WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
You can add one by overriding the CWnd::WindowProc() function in your receiving application (use classwizard in either the dialog in an MFC dialog app, or the MainFrm in a Single / Multiple Document MFC app)
You send the message to all windows like this:
ULONG ulRC = BSM_APPLICATIONS;
BroadcastSystemMessage(BSF_IGNORECURRENTTASK | BSF_FORCEIFHUNG, // do not send message to this process and don't hang
&ulRC, // broadcast only to applications
WM_YOUR_CUSTOM_MESSAGE, // message registered in previous step
0, // wParam message-specific value
0); // lParam message-specific value
If you need to pass some information with the message, you can also make use of the wParam and lParam values in the message.
There is one big assumption in the current answers. You normally send messages to processes, not applications. This is a huge difference. There could be zero, one or more instances of the MFC application running.
In the case of zero applications, the DLL will have to call CreateProcess. CreateProcess allows the DLL to pass command-line arguments to your MFC app.
In the case of one MFC application, the message-based solutions offered above will work.
In the case of more than one running MFC application, they'll have different HWNDs. THe DLL picks the application(s) by picking which HWND to send the message to. The logic by which an HWND is picked is outside the scope of this question. One common solution is to just send the message to the HWND's of all running instances.
Finding out how many instances of your application are running is achieved by Process Enumeration
I want to do some processing when a particular dialog is opened but I am not able to find any way to get notification when that dialog is opened.
Is there any way to get notification in application for opening of a particular windows dialog?
The only available information about the dialog is its title and its unique.
The general solution is to use windows hooks, filter to WH_CBT, filter to WM_CREATE, or something like that, get the window text and see if it is the one of your interest.
One more important point: in hook you should use SetWindowLongPtr() to set window process to your own function, that will actually receive WM_CREATE event. In all calls this function should call the original window procedure.
You can also use a CBT Hook to watch window creation messages. You'll have access to the CREATSTRUCT used to create the actual window, eg, the title and class name. You can prevent the window from being created in your hook, modify the size, etc.
EDIT: sorry didn't notice that you don't have the code yourself but only the title. So I think the other posts solution is what you need
The event handling in win32 applications is done via a so called windows procedure which is a callback function with the following signature:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
This callback gets called by windows every time there is a message for windows which are registered with this callback function. One of the first messages send to a new window is the WM_CREATE message.
If you are creating your windows "by hand" with win32 API, then there should be a static callback function like the one below where you can filter for the WM_CREATE message.
LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch( message )
{
case WM_CREATE:
// do what ever you want
return 0;
case default:
return DefWndProc( hwnd, message, wParam, lParam );
}
}
If you use MFC dialogs (CDialog) then you can overwrite the function CDialog::OnInitDialog().
OK, the way to do this is to use SetWindowsHookEx(WH_SYSMSGFILTER,...)
You'll be getting a lot more callbacks than you really need. and global hooks are a real drain on system performance (they can force the system to serialize things that would normally run independently)
be sure to read the Remarks, especially this part:
SetWindowsHookEx can be used to inject a DLL into another process. A 32-bit DLL cannot be injected into a 64-bit process, and a 64-bit DLL cannot be injected into a 32-bit process. If an application requires the use of hooks in other processes, it is required that a 32-bit application call SetWindowsHookEx to inject a 32-bit DLL into 32-bit processes, and a 64-bit application call SetWindowsHookEx to inject a 64-bit DLL into 64-bit processes. The 32-bit and 64-bit DLLs must have different names.
Your hook must live in a dll, and the dll will end up loaded into other process's address space, so you won't it won't have access to your procees's address space, you will have to set up some sort of interprocess communication between your hook and your app.
On the whole I'd say this sounds like a really bad idea.