April 29, 2024, 06:10:48 AM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


Question about global Hook (using a DLL )

Started by pistol350, October 19, 2009, 03:04:53 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

pistol350

October 19, 2009, 03:04:53 PM Last Edit: October 19, 2009, 03:13:59 PM by pistol350
Hello all!
What i'm trying to do is just creating a global hook using a DLL to monitor given events on my machine.
The DLL is only attached to the process of my Exe so i guess there is something missing in my DLL code to get it attached to every process.


From MSDN : http://msdn.microsoft.com/en-us/library/ms644990(VS.85).aspx

hMod
[in] Handle to the DLL containing the hook procedure pointed to by the lpfn parameter. The hMod parameter must be set to NULL if the dwThreadId parameter specifies a thread created by the current process and if the hook procedure is within the code associated with the current process.

dwThreadId
[in] Specifies 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.


Then i guess the dwThread parameter should be set to "0", but when i do so, the SetWindowsHookEx() function returns 0 to my hhk variable so the hook does not work.
Any idea  please ?
I'm pretty sure it is about my modulehandle parameter but hhk = SetWindowsHookEx(WH_CBT, &kbdWinAmp, GetModuleHandle(NULL), 0) does not seem to work either.

Below is the code of my DLL.


$MAIN
$include "WINDOWSSDK.inc" :' $include "Windows.inc"
export StartHook
export EndHook

DECLARE StartHook(),INT
DECLARE EndHook()

Uint HWin
HINSTANCE thismod : 'HINSTANCE thismod
uint hhk : 'HHOOK hhk

' BOOL WINAPI DllMain(HINSTANCE hDll, DWORD dwReason, LPVOID Reserved)
'SUB DllMain(hDll:HINSTANCE, dwReason:Dword,Reserved:LPVOID),INT
'  if(dwReason = DLL_PROCESS_ATTACH) then thismod = hDll
'  return 1
'ENDSUB

'LRESULT CALLBACK kbdWinAmp(int nCode, WPARAM wParam, LPARAM lParam) {
SUB kbdWinAmp(nCode:int,wParam:uint,lParam:pointer)
IF(nCode >= 0)
HWin = FindWindowA(NULL,"Window Hook")
SendMessage(HWin,99,1,str$(nCode))
'if(nCode = HCBT_ACTIVATE) then MessageBox(NULL, "The system is about to activate a window.", "Information", MB_ICONINFORMATION)
'if(nCode = HCBT_CREATEWND) then MessageBox(NULL, "A window is about to be created.", "Information", MB_ICONINFORMATION)
'if(nCode = HCBT_SETFOCUS) then MessageBox(NULL, "A window is about to receive the keyboard focus.", "Information", MB_ICONINFORMATION)
if(nCode = HCBT_MINMAX) THEN messagebox(Null, "A window is about to be minimized or maximized", "Information", MB_ICONINFORMATION)
if(nCode = HCBT_MOVESIZE) THEN MessageBox(NULL, "A window is about to be moved or sized.", "Information", MB_ICONINFORMATION)
ENDIF
return CallNextHookEx(hhk, nCode, wParam, lParam)
ENDSUB

/****************************************************************************************************/

sub StartHook(),int
if (hhk = 0)
'hhk = SetWindowsHookEx(WH_CBT, &kbdWinAmp, NULL, GetCurrentThreadId()) : for thread hook
hhk = SetWindowsHookEx(WH_CBT, &kbdWinAmp, NULL, NULL)
endif
return hhk
Endsub


sub EndHook()
if (hhk>0)
UnhookWindowsHookEx(hhk)
hhk = 0
ENDIF
return
Endsub
/****************************************************************************************************/


And here is the code to my main exe file
$main
'$use "WinHookDll.lib"
$include "WINDOWSSDK.inc"

' declare exported functions()
DECLARE "WinHookDll.dll", StartHook(),int
DECLARE "WinHookDll.dll", EndHook()

/* Controls constants */
CONST BUTTON_1 = 1
CONST BUTTON_2 = 2
CONST BUTTON_3 = 3
CONST STATIC_4 = 4
CONST STATIC_5 = 5

/* Creating our main Dialog */
DIALOG d1
CREATEDIALOG d1,0,0,300,202,0x80CB0080,0,"Window Hook",&d1_handler
CONTROL d1,@BUTTON,"Enable",15,24,70,20,0x50000000,BUTTON_1
CONTROL d1,@BUTTON,"Disable",216,24,70,20,0x50000000,BUTTON_2
CONTROL d1,@BUTTON,"Quit",115,53,70,20,0x50000000,BUTTON_3
CONTROL d1,@STATIC,"Window Hook",16,124,269,71,0x50000101,STATIC_4
CONTROL d1,@STATIC,"MSG :",16,154,269,71,0x50000101,STATIC_5

/* Define and Init our Variables */
INT enable = FALSE
int run = 1
SHOWDIALOG d1 :' Display our Window
WAITUNTIL run = 0
' IF HOOK is enable, then disable it
if(enable>0)
DisableHooK()
endif
CLOSEDIALOG d1,@IDOK :' Close our Window at the end of program
END

SUB d1_handler
SELECT @MESSAGE
CASE 99
         SETCONTROLTEXT d1, 5, "MSG : "+str$(@LPARAM)+"\n"+"Hook enable : "+ str$(enable)+"\n"+"MSG 99 received!"
CASE @IDINITDIALOG
CENTERWINDOW d1
/* Initialize any controls here */
CASE @IDCLOSEWINDOW
run=0
CASE @IDCONTROL
SELECT @CONTROLID
CASE BUTTON_1
IF @NOTIFYCODE = 0
/*button clicked*/
if(enable = 0)
enable = TRUE
StartHook()
endif
ENDIF
CASE BUTTON_2
IF @NOTIFYCODE = 0
/*button clicked*/
if(enable>0)
DisableHooK()
endif
ENDIF
CASE BUTTON_3
IF @NOTIFYCODE = 0
/*button clicked*/
run=0
ENDIF
ENDSELECT
DEFAULT
return FALSE
ENDSELECT
RETURN
ENDSUB

SUB DisableHooK()
enable = FALSE
EndHook()
RETURN
ENDSUB
Regards,

Peter B.

sapero

October 19, 2009, 05:31:10 PM #1 Last Edit: October 19, 2009, 05:39:06 PM by sapero
If you want to install a hook for external applications, you need to specify the third parameter for SetWindowsHookEx:
hhk = SetWindowsHookEx(WH_CBT, &kbdWinAmp, GetModuleHandle("WinHookDll.dll"), NULL)
If SetWindowsHookEx is called from a dll, you can pass _hinstance instead GetModuleHandle (dll name is not required).

By the way, for WH_CBT hook you don't need a dll, the callback can be any function from yor .exe:
hhk = SetWindowsHookEx(WH_CBT, &CBTProc, 0, GetCurrentThreadId())

If you want to act like explorer (WH_SHELL like hook), you don't even need to call SetWindowsHookEx - use RegisterShellHookWindow api providing only your window handle. You will be notified with standard windows messages:
UINT WM_SHELLHOOK

sub handler()
...
case @IDCREATE
WM_SHELLHOOK = RegisterWindowMessage("SHELLHOOK")
RegisterShellHookWindow(win.hwnd)

case @IDDESTROY
DeregisterShellHookWindow(win.hwnd)

case WM_SHELLHOOK
select @wParam
case HSHELL_***


Note: The hhk global variable in your dll (initialized in SUB kbdWinAmp) will be nonzero only in the context of your process. It will be zeroed when loaded into another process, so CallNextHookEx will be ignored. Ebasic does not have any direct support for shared data sections, you need external storage for this (registry, file)

pistol350

October 20, 2009, 02:38:29 AM #2 Last Edit: October 20, 2009, 03:26:33 AM by pistol350
hi Sapero!
Thank you for your help.
I will apply the changes that you suggested and surely come back with further questions.

Actually, i'm aware of the fact that using a DLL is not necessary for this WH_CBT hook,
but i'm just starting to explore the hooking world and i plan to go further playing with advanced hooking techniques where DLLs will be necessary.

Quote
...
Note: The hhk global variable in your dll (initialized in SUB kbdWinAmp) will be nonzero only in the context of your process. It will be zeroed when loaded into another process, so CallNextHookEx will be ignored. Ebasic does not have any direct support for shared data sections, you need external storage for this (registry, file)
...
Anyway, i now understand why i could not achieve the results expected. I'll try to find a workaround solution to this problem then.
Thanks again

PS :
After applying this
hhk = SetWindowsHookEx(WH_CBT, &kbdWinAmp, GetModuleHandle("WinHookDll.dll"), NULL)
and recompile my project, the program worked as i wished, but hhk = SetWindowsHookEx(WH_CBT, &kbdWinAmp, GetModuleHandle(NULL), NULL) does not work.
So i guess the name of my DLL is really required if i use GetModuleHandle() function instead of _hinstance.
I'll dig deeper.
Regards,

Peter B.

pistol350

QuoteNote: The hhk global variable in your dll (initialized in SUB kbdWinAmp) will be nonzero only in the context of your process. It will be zeroed when loaded into another process, so CallNextHookEx will be ignored. Ebasic does not have any direct support for shared data sections, you need external storage for this (registry, file)

Ok, now that i've read a bit more on the subject, i think i see what you mean about "shared data sections".
So here is my question :
Keeping in mind that CallNextHookEx() is ignored when i get my Hhk variable loaded into another process different from mine (because of Ebasic not directly supporting shared data sections),
does it mean that other hooks in the chain are not called by the function ? Then i think in that case my program may create dysfunction in other processes.

So to prevent this, How can i use external storage  as a replacement for shared data storage ?
I guess i need to read a bit more.  :D
Regards,

Peter B.

sapero

If you read the doc:LRESULT CallNextHookEx(
HHOOK hhk,
int nCode,
WPARAM wParam,
LPARAM lParam
);

hhk [in] Windows 95/98/ME: Handle to the current hook. [..].
Windows NT/XP/2003: Ignored.


If your hook is running on XP, you can pass 0 as hhk, and don't worry about hook handle. But on 95/98/ME you need the handle if the next hook should be called:

/* dll code */
HHOOK g_hhk

sub InstallHook()
g_hhk = SetWindowsHookEx(...)
mysettings.registry.Write("hhk", REG_DWORD, &hhk, len(hhk))

sub UninstallHook()
UnhookWindowsHookEx(g_hhk)
mysettings.registry.Remove("hhk")


sub HookCallback()
...
if (!g_hhk) then mysettings.registry.Read("hhk", &g_hhk, len(g_hhk))
return CallNextHookEx(g_hhk)