[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 314
  • Last Modified:

System-wide hook works well in Win16 but doesn't work in Win32

Hi,

I have a system-wide hook function in DLL (Win16-based). That function sends all WM_CHAR messages to the main window of my .EXE program (Win16-based too). It works well. It sends WM_CHAR whenever I type in any application.

Yesterday, I want it supports taskbar icon notification so I change my project target (both .DLL and .EXE) to Win32 and they didn't work as before. The hook function didn't receive message when my window lost focus. In another word, it seems that hook associates only to one task (my .EXE).

For simple, I change my system-wide hook function to:
//------------------------------------------------------------------------------
LRESULT CALLBACK __export HookProc( int nCode, WPARAM Param, LPARAM lParam )
   {
            if ( nCode >= 0 ){
                  msg = * ( MSG far * ) lParam;
                  if( ((MSG far *)lParam)->message == WM_CHAR )
                        MessageBox( 0, "WM_CHAR", "Receive", MB_OK );
            }

            return CallNextHookEx( hhook, nCode, wParam, lParam);
      }

but I couldn't receive any message box when I type in other application.

Please help me. Thanks.

I have only 30 points and many questions now, please understand me! :-)
0
toannds
Asked:
toannds
  • 10
  • 4
  • 2
1 Solution
 
toanndsAuthor Commented:
Edited text of question
0
 
toanndsAuthor Commented:
Edited text of question
0
 
migelCommented:
Do you use SetWindowsHook ? If it`s true just call SetWindowsHookEx instead.
set  DWORD  dwThreadID parameter to the 0 to set system wide hook.

0
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

 
toanndsAuthor Commented:
I already used
HHOOK SetWindowsHookEx(idHook, hkprc, hinst, htask) in my program with htask = 0.

I didn't tell you another strange:

The Win32.hlp said that we don't need to use MakeProcInstance in Win32 version, we can pass directly function address to hkprc.
But if I do what it said, SetWindowsHookEx return NULL (an error) and of course, I don't receive any message at all. By the way, can you show me which function I can use to get error in this case?

0
 
migelCommented:
GetLastError
0
 
alexoCommented:
toannds, a systemwide hook in win32 MUST reside in a DLL.
0
 
toanndsAuthor Commented:
That's what I did: my system-wide hook resides in my DLL, it posts message to my main window.
0
 
alexoCommented:
OK, we have progress...  :-)
I have answered several hook-related questions in the past.  Here are URLs to two of them.  Please read the whole discussion (including the comments) and look at the sample code.
    http://www.experts-exchange.com/Q.10063288 (5 points)
    http://www.experts-exchange.com/Q.10069661 (4 points)

0
 
toanndsAuthor Commented:
My already used SetWindowHooksEx in my DLL.
0
 
toanndsAuthor Commented:
I'm so sorry. I wasn't intend to post previous message. That was a mistake. I'm reading alexo's answers in the past...
0
 
toanndsAuthor Commented:
alexo, thank you for your answers (and I lost 9 points :-) ). Now I know hhook must be the shared data for difference tasks. I use Borland C++ 4.5 so there're some differences from your answers. My DLL project includes 3 files:

sysdata.cpp
syshook.cpp
syshook.def

The sysdata.cpp contains variables in shared data segment.
The syshook.cpp set up system-wide hook and contains hook proc.
//--------------------------------------------------------------
// sysdata.cpp
// All variables in this file are in another shared data segment besides the default DLL segment.
//--------------------------------------------------------------
#pragma option -zRSHAREDATA     //   Sets the name of the initialized data segment.
#pragma option -zSSHAREGROUP      // Sets the name of the initialized data segment group.
#pragma option -zTSHARECLASS      // Sets the name of the initialized data segment class.

#include <windows.h>

HHOOK hhook = 0;
HWND __export hwndHookReport = 0;
UINT __export wm_hookreport = 0;
MSG __export msg = {0};
//--------------------------------------------------------------
// syshook.cpp
//--------------------------------------------------------------
#include <windows.h>

HINSTANCE hInstance;
// these variables are in the shared segment
extern HHOOK hhook;
extern HWND hwndHookReport;
extern UINT wm_hookreport;
//------------------------------------------------------------------------------
LRESULT CALLBACK __export HookProc( int nCode, WPARAM Param, LPARAM lParam )
    {
        if ( nCode >= 0 ){
             if( ((MSG far *)lParam)->message == WM_CHAR )
                  MessageBox( 0, "WM_CHAR", "Receive", MB_OK );
        }
        return CallNextHookEx( hhook, nCode, wParam, lParam);
    }
//------------------------------------------------------------------------------
int far __export InstallSystemHook( HWND hwnd, UINT wm_report, int idHook )
//
//    hwnd: The window that receive wm_report every time HookProc get a message
//
    {
        FARPROC lpFunc;

        hwndHookReport = hwnd;
        wm_hookreport = wm_report;
        lpFunc = MakeProcInstance( (FARPROC) HookProc, hInstance );
        hhook = SetWindowsHookEx( idHook, (HOOKPROC) lpFunc, hInstance, 0 );
        return (int) hhook;
    }
//------------------------------------------------------------------------------
int far __export UninstallSystemHook()
    {
        return UnhookWindowsHookEx( hhook );
    }
//------------------------------------------------------------------------------
int CALLBACK LibMain( HINSTANCE hinst, WORD wDataSeg, WORD cbHeap, LPSTR lpszCmdLine )
    {
        hInstance = hinst;
        return 1;
    }
//--------------------------------------------------------------
// syshook.dll
//--------------------------------------------------------------
LIBRARY            SYSHOOK
DATA            MULTIPLE NONSHARED
SEGMENTS      SHAREDATA CLASS 'SHARECLASS' SHARED
//--------------------------------------------------------------

This .DLL is used only by one .EXE at a time. After sharing hhook and some other variables I couldn't resolve anything. You see: I write the line MessageBox(..) immediately after HookProc recieves WM_CHAR but the message box is showed only when the main window of my .EXE (that uses DLL) yields focus. It's likely not a system-wide hook manner but thread hook although the last parameter of SetWIndowsHookEx is NULL.

Ok, I'll try more research...

0
 
toanndsAuthor Commented:
Alexo,

Thank you very much. I change to VC++ 5 and work well. However I need to change your code. I couldn't understand why I need to export functions & definition of share data section in .DEF, otherwise (use dllexport at function prototype) my hook function didn't work! Do you have any idea?
I want to give you points, please post your answer instead of comment :-) ...

0
 
alexoCommented:
>> Do you have any idea?
Possibly C++ name mangling.  Did you try declaring the funcs as extern "C"?
0
 
toanndsAuthor Commented:
Alexo, you're right! Now my DLL catch any WM_CHAR.
I want to ask you more :-)

I declare a variable of MSG type in shared section and export it in EXPORTS section of .DEF of my .DLL. Every time when my hook function receives a message it copies message to this shared variable and informs my .EXE by SendMessage(). My .EXE receive message and check the share variable. However my .EXE always receives correct wParam, lParam but not *(MSG far *)lParam.




0
 
toanndsAuthor Commented:
Alexo, you're right! Now my DLL catch any WM_CHAR.
I want to ask you more :-)

I declare a variable of MSG type in shared section and export it in EXPORTS section of .DEF of my .DLL. Every time when my hook function receives a message it copies message to this shared variable and informs my .EXE by SendMessage(). My .EXE receive message and check the share variable. However my .EXE always receives correct wParam, lParam but not *(MSG far *)lParam.




0
 
alexoCommented:
>> my .EXE always receives correct wParam, lParam but not *(MSG far *)lParam.
Huh???
0

Featured Post

Take Control of Web Hosting For Your Clients

As a web developer or IT admin, successfully managing multiple client accounts can be challenging. In this webinar we will look at the tools provided by Media Temple and Plesk to make managing your clients’ hosting easier.

  • 10
  • 4
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now