yehiaeg
asked on
WH_CBT Strange Behavior
Hello,
I'm trying to use WH_CBT hooking to get a list of any activated process, however while testing i only get several HCBT_CLICKSKIPPED message codes at first and that's its, i don't receive any other messages which i am interested in like HCBT_CREATEWND or HCBT_ACTIVATE
Here is my full implementation:
//************************ ********** ********** ********** ********** ********** ********** *****
library HookLib;
uses
SysUtils, Classes, Windows;
type
TClientCallBack = procedure(Code,wParam : integer) of object;
var fHookhandle: THandle;
clientFunction : TClientCallBack;
{$R *.res}
function callbackFunction(Code, wParam, lParam: Integer): Integer; stdcall;
begin
OutputDebugString(PChar('c ode from dll' + InttoStr(Code))); // always prints 6 (HCBT_CLICKSKIPPED)
if (Code < 0) then begin
result := CallNextHookEx(fHookhandle , Code, wParam, lParam);
exit;
end;
clientFunction(Code,wParam ); //Calls client callback function
result := CallNextHookEx(fHookhandle , Code, wParam, lParam);
end;
function InstallCBTHook(ClientCallB ackFunctio n: TClientCallBack):boolean; stdcall;
begin
clientfunction := ClientCallBackFunction;
fHookhandle := SetWindowsHookEx(WH_CBT, @callbackFunction, hInstance, 0);
if fHookhandle > 0 then result := true else result := false;
end;
procedure UninstallCBTHook();stdcall ;
begin
UnhookWindowsHookEx(fHookh andle);
end;
exports
InstallCBTHook, UninstallCBTHook;
begin
end.
//************************ ********** ********** ********** ********** *********
I'm trying to use WH_CBT hooking to get a list of any activated process, however while testing i only get several HCBT_CLICKSKIPPED message codes at first and that's its, i don't receive any other messages which i am interested in like HCBT_CREATEWND or HCBT_ACTIVATE
Here is my full implementation:
//************************
library HookLib;
uses
SysUtils, Classes, Windows;
type
TClientCallBack = procedure(Code,wParam : integer) of object;
var fHookhandle: THandle;
clientFunction : TClientCallBack;
{$R *.res}
function callbackFunction(Code, wParam, lParam: Integer): Integer; stdcall;
begin
OutputDebugString(PChar('c
if (Code < 0) then begin
result := CallNextHookEx(fHookhandle
exit;
end;
clientFunction(Code,wParam
result := CallNextHookEx(fHookhandle
end;
function InstallCBTHook(ClientCallB
begin
clientfunction := ClientCallBackFunction;
fHookhandle := SetWindowsHookEx(WH_CBT, @callbackFunction, hInstance, 0);
if fHookhandle > 0 then result := true else result := false;
end;
procedure UninstallCBTHook();stdcall
begin
UnhookWindowsHookEx(fHookh
end;
exports
InstallCBTHook, UninstallCBTHook;
begin
end.
//************************
>> clientfunction := ClientCallBackFunction;
You're setting this value only in 1 process (in that one which sets the hook). This .dll is then loaded into other processes, which have their own memory space - value of clientfunction is not ClientCallBackFunction in their memory.
You may test it by setting default value of variable when defining it (var test : integer = 0;), changing it's value in InstallCBTHook and then doing something like "if test = 0 then MessageBeep(0);" in callback function. You'll probably hear beeps, which mean that "test" variable has default value, although it's changed in InstallCBTHook.
I'm not sure what's the best way to solve this though. Could be solved by using memory mapped files (I haven't done that yet) or sending messages with SendMessage() to comunicate with main application.
You're setting this value only in 1 process (in that one which sets the hook). This .dll is then loaded into other processes, which have their own memory space - value of clientfunction is not ClientCallBackFunction in their memory.
You may test it by setting default value of variable when defining it (var test : integer = 0;), changing it's value in InstallCBTHook and then doing something like "if test = 0 then MessageBeep(0);" in callback function. You'll probably hear beeps, which mean that "test" variable has default value, although it's changed in InstallCBTHook.
I'm not sure what's the best way to solve this though. Could be solved by using memory mapped files (I haven't done that yet) or sending messages with SendMessage() to comunicate with main application.
function callbackFunction( Code : Integer; WParam : wParam; LParam : lParam ): LResult; stdcall;
begin
if Code >= 0 then
begin
OutputDebugString( PChar( 'code from dll ' + IntToStr( Code ) ) );
clientFunction( Code, WParam );
end;
result := CallNextHookEx( fHookhandle, Code, wParam, lParam );
end;
begin
if Code >= 0 then
begin
OutputDebugString( PChar( 'code from dll ' + IntToStr( Code ) ) );
clientFunction( Code, WParam );
end;
result := CallNextHookEx( fHookhandle, Code, wParam, lParam );
end;
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
ok i followed what you were saying. ZhaawZ about using the memory mapped file, and arioh about the new function, however i still have the same behavior, several HCBT_CLICKSKIPPED messages and that's it:
library HookLib;
uses
SysUtils, Classes, Windows;
type
//TClientCallBack = procedure(Code,wParam : integer) of object;
PSharedRecord = ^TSharedRecord;
TSharedRecord = record
fHookhandle: THandle;
clientHwnd : HWND;
fInstallProcess: DWORD;
end;
var fMemoryFile: THandle = 0;
sharedRec: PSharedRecord = nil;
uiMyMsg: UINT = 0;
{$R *.res}
function callbackFunction(Code, wParam, lParam: Integer): Integer; stdcall;
begin
if Code >= 0 then begin
OutputDebugString(PChar('c ode from dll' + InttoStr(Code)));
if sharedRec <> nil then begin
PostMessage(sharedRec^.cli entHwnd, uiMyMsg, Code, wParam);
end;
end;
result := CallNextHookEx(sharedRec^. fHookhandl e, Code, wParam, lParam);
end;
function InstallCBTHook(clientHwnd : HWND): boolean ; stdcall;
begin
result := false;
fMemoryFile := CreateFileMapping($FFFFFFF F, nil, PAGE_READWRITE,0, // size: high 32-bits
SizeOf(TSharedRecord), 'auniquename');
if (fMemoryFile <> 0 ) then begin
sharedRec := MapViewOfFile(fMemoryFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if sharedRec <> nil then begin
sharedRec^.clientHwnd := clientHwnd ;
sharedRec^.fInstallProcess := GetCurrentProcessId;
sharedRec^.fHookhandle := SetWindowsHookEx(WH_CBT, @callbackFunction, hInstance, 0);
result := true ;
end;
end
else result := false;
end;
procedure UninstallCBTHook();stdcall ;
begin
if assigned(sharedRec) then begin
if sharedRec^.fInstallProcess = GetCurrentProcessId then begin
UnhookWindowsHookEx(shared Rec^.fHook handle);
sharedRec^.fHookhandle := 0;
sharedRec^.clientHwnd := 0;
sharedRec^.fInstallProcess := 0;
end;
UnmapViewOfFile(sharedRec) ;
sharedRec := nil;
end;
if (fMemoryFile <> 0 ) then begin
CloseHandle(fMemoryFile);
fMemoryFile := 0;
end;
end;
procedure DllEntry(dwReason : DWORD);
begin
if (dwReason = Dll_Process_Attach) then begin
uiMyMsg := RegisterWindowMessage('aun iquemsgnam e');
if uiMyMsg <> 0 then begin
fMemoryFile := OpenFileMapping(FILE_MAP_W RITE, False, 'auniquemsgname');
sharedRec := MapViewOfFile(fMemoryFile, FILE_MAP_READ, 0, 0, 0);
if sharedRec = nil then UninstallCBTHook();
end;
end
else if (dwReason = Dll_Process_Detach) then begin
UninstallCBTHook();
end;
end;
exports
InstallCBTHook, UninstallCBTHook, callbackFunction;
begin
DisableThreadLibraryCalls( hInstance) ;
DllProc := @DLLEntry;
DllEntry(DLL_PROCESS_ATTAC H);
end.
library HookLib;
uses
SysUtils, Classes, Windows;
type
//TClientCallBack = procedure(Code,wParam : integer) of object;
PSharedRecord = ^TSharedRecord;
TSharedRecord = record
fHookhandle: THandle;
clientHwnd : HWND;
fInstallProcess: DWORD;
end;
var fMemoryFile: THandle = 0;
sharedRec: PSharedRecord = nil;
uiMyMsg: UINT = 0;
{$R *.res}
function callbackFunction(Code, wParam, lParam: Integer): Integer; stdcall;
begin
if Code >= 0 then begin
OutputDebugString(PChar('c
if sharedRec <> nil then begin
PostMessage(sharedRec^.cli
end;
end;
result := CallNextHookEx(sharedRec^.
end;
function InstallCBTHook(clientHwnd : HWND): boolean ; stdcall;
begin
result := false;
fMemoryFile := CreateFileMapping($FFFFFFF
SizeOf(TSharedRecord), 'auniquename');
if (fMemoryFile <> 0 ) then begin
sharedRec := MapViewOfFile(fMemoryFile,
if sharedRec <> nil then begin
sharedRec^.clientHwnd := clientHwnd ;
sharedRec^.fInstallProcess
sharedRec^.fHookhandle := SetWindowsHookEx(WH_CBT, @callbackFunction, hInstance, 0);
result := true ;
end;
end
else result := false;
end;
procedure UninstallCBTHook();stdcall
begin
if assigned(sharedRec) then begin
if sharedRec^.fInstallProcess
UnhookWindowsHookEx(shared
sharedRec^.fHookhandle := 0;
sharedRec^.clientHwnd := 0;
sharedRec^.fInstallProcess
end;
UnmapViewOfFile(sharedRec)
sharedRec := nil;
end;
if (fMemoryFile <> 0 ) then begin
CloseHandle(fMemoryFile);
fMemoryFile := 0;
end;
end;
procedure DllEntry(dwReason : DWORD);
begin
if (dwReason = Dll_Process_Attach) then begin
uiMyMsg := RegisterWindowMessage('aun
if uiMyMsg <> 0 then begin
fMemoryFile := OpenFileMapping(FILE_MAP_W
sharedRec := MapViewOfFile(fMemoryFile,
if sharedRec = nil then UninstallCBTHook();
end;
end
else if (dwReason = Dll_Process_Detach) then begin
UninstallCBTHook();
end;
end;
exports
InstallCBTHook, UninstallCBTHook, callbackFunction;
begin
DisableThreadLibraryCalls(
DllProc := @DLLEntry;
DllEntry(DLL_PROCESS_ATTAC
end.
Forced accept.
Computer101
EE Admin
Computer101
EE Admin
ASKER