Solved

Windows global Hooks

Posted on 2001-08-10
3
1,479 Views
Last Modified: 2013-12-03
Hi all,

Need help with Windows Hooks...

I'm trying to insert a global Mouse Hook into the system chain. But it's not working working according to plan. It almost looks like it's active only on my current application.

I have the main application that inserts the hook by calling SetWindowsHookEx. The hook procedure itself resides in a DLL. Right now I have the hook procedure simply intercept the WM_MOUSEMOVE message globaly accross all applications. When a message is intercepted, I display the window handle (hwnd) and x/y positions of the mouse associated with the message on my main application (exe) by simply calling the DrawText function within my WM_PAINT. The problem is that the message is only being displayed when the hook intercepts WM_MOUSEMOVE messages for my application ONLY instead of all of the windows on the system.

Here's what I have:
In my main application (.exe) I have:

//global declarations
typedef void (*MYPROC) (LPTSTR msg);
MYPROC  ProcAdd;
HOOKPROC ProcHook;
HINSTANCE hdll;
char szStartMsg[1024];



//in my WM_CREATE message
//ProcAdd - getMyMsg is called to get a string from the DLL
//ProcHook - myMouseHook is the MouseProc hook function
hdll=LoadLibrary((LPCTSTR)szAppDll);//load the library
if (hdll!=NULL){
    (ProcAdd) = ((MYPROC)  GetProcAddress(hdll,(LPCSTR)"getMyMsg"));
    (ProcHook)= ((HOOKPROC)GetProcAddress(hdll,(LPCSTR)"myMouseHook"));

//install the hook GLOBALLY
hhook = SetWindowsHookEx(WH_MOUSE,ProcHook,hdll,0);
}



//in my WM_PAINT message
//call getMyMsg to get a string from the dll and place it in msg
(ProcAdd)(msg);
hdc = BeginPaint (hwnd, &ps) ;
GetClientRect (hwnd, &rect) ;
sprintf(szStartMsg,"%s",msg);
DrawText (hdc, szStartMsg, -1, &rect,DT_SINGLELINE) ;
EndPaint (hwnd, &ps) ;




Then, in my DLL the ProcAdd (getMymsg) function is defined as:
extern "C" void getMyMsg(LPTSTR msg){    
     sprintf(msg,szHook);
}//end getMyInt


And, my MouseProc hook function (myMouseHook) is defined as:
extern "C" LRESULT CALLBACK myMouseHook(int nCode, WPARAM wParam, LPARAM lParam){
   MOUSEHOOKSTRUCT *PMOUSEHOOKSTRUCT;


   if (nCode < 0){ // do not process the message
      return CallNextHookEx(hhook, nCode, wParam, lParam);

   }else if (nCode==HC_ACTION){
      PMOUSEHOOKSTRUCT=(MOUSEHOOKSTRUCT *)lParam;

      //capture the WM_MOUSEMOVE          
      if (wParam==WM_MOUSEMOVE){
         memset(szHook,0,1024);

         //place the hwnd, x and y data in the szHook variable
         sprintf(szHook,"hwnd=[%u], x=[%i],y=[%i]",
             PMOUSEHOOKSTRUCT->hwnd,
             PMOUSEHOOKSTRUCT->pt.x,
             PMOUSEHOOKSTRUCT->pt.y);
      }//end if wParam
   }//end if (nCode)
     
   return CallNextHookEx(hhook, nCode, wParam, lParam);
}//end myMouseHook


szHook is being written to in the hook function.
Then szHook is returned to the calling app through a call to getMyMsg.
Therefore, each time the application receives a WM_PAINT message, it should
display the current mouse position and window handle of the window in which
the mouse resides over...

In the main app, I have a 1 second timer enabled to force a WM_PAINT and
therefore repaint the window...


Like I said above, the application does display the mouse position and
window handle every second as long as I move the mouse over my main application. As
soon as I move the mouse over another application, my app doesn't display the message
even though it's being repainted.

If you need additional info, e-mail me at santos@traxxinc.net or just post a message here.

Any help would be appreciated...

Thanks
Vorlon
0
Comment
Question by:vorlon
3 Comments
 
LVL 5

Accepted Solution

by:
robpitt earned 100 total points
Comment Utility
There are numerous samples of using SetWindowsHookEx with a dll. I suggest searching msdn.microsoft.com for "SetWindowsHookEx DLL" and reading some of the documents found.

Here is a sample of my own which deals with WH_CBT though you could adapt it to any hook type:
http://website.lineone.net/~codebox/focuslog.zip


The key point is that the hHook value returned by SetWindowsHook() needs to be propagated to all other instances of the hook DLL as loaded by other processes. The easiest way to do this is via a shared data segment. Any other data that needs to be accesible to all instances of the DLL must also be shared between DLL instances.

Rob
0
 
LVL 20

Expert Comment

by:Madshi
Comment Utility
Rob is absolutely right (of course). Just a little additional explanation:

When doing global hooks, your dll is not only loaded into your own process, but a copy of your dll is loaded into each and every GUI processes system wide (that is the reason why the callback function has to be in a dll). But the global variables of the dll are only correctly initialized in the copy of the dll, which is loaded into your own application. Furthermore you're only calling the "getMyMsg" function of the copy of the dll, that is loaded in your own application. All the other dlls have their own "szHook" buffers.

The solution is to put at least the szHook and the hHook variable into a shared segment, so that they are shared between all loaded copies of your dll. Please don't ask me about how the syntax for shared segments is in C++ (I'm a Delphi programmer), but I guess, you'll find enough examples with it on the net...

Regards, Madshi.
0
 
LVL 2

Author Comment

by:vorlon
Comment Utility
Thanks guys...

It totally escaped me what Madshi said:
"When doing global hooks, your dll is not only loaded into your own process, but a copy of your dll is
loaded into each and every GUI processes system wide (that is the reason why the callback function has
to be in a dll). "

Once I shared the memory (easy), it all worked...


Since Rob was the first one to suggest a shared memory correction, you get the points...


Thanks both of you...
Vorlon
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

This article describes a technique for converting RTF (Rich Text Format) data to HTML and provides C++ source that does it all in just a few lines of code. Although RTF is coming to be considered a "legacy" format, it is still in common use... po…
zlib is a free compression library (a DLL) on which the popular gzip utility is built.  In this article, we'll see how to use the zlib functions to compress and decompress data in memory; that is, without needing to use a temporary file.  We'll be c…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now