Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

SetWindowsHookEx and ShellProc

214 views
Skip to first unread message

Paulo Cordeiro

unread,
Oct 31, 1999, 2:00:00 AM10/31/99
to
Hello,

Where to find a code example using:

* SetWindowsHookEx
* ShellProc

Thankful,


Paulo Cordeiro
pauloc...@cids.com.br


Tomislav Kardaš

unread,
Nov 3, 1999, 3:00:00 AM11/3/99
to
Hi Paulo!

On Sun, 31 Oct 1999 15:07:02 -0200, "Paulo Cordeiro"
<pauloc...@cids.com.br> wrote:

>Where to find a code example using:
>
> * SetWindowsHookEx
> * ShellProc

{$C FIXED PRELOAD PERMANENT}

library HookDLL;

uses
Windows,
Messages,
HookRec in 'HookRec.pas';

var
hObjHandle: THandle; {Variable for the file mapping object}
lpHookRec: PHookRec; {Pointer to our hook record}

procedure ErrMessage(msg: string);
begin
MessageBox(0, PChar(msg), 'Hook DLL', MB_OK);
end;

procedure MapFileMemory(dwAllocSize : DWORD);
var
bCreated: boolean;
begin
{Create a process wide memory mapped variable}
hObjHandle := CreateFileMapping($FFFFFFFF, NIL, PAGE_READWRITE, 0,
dwAllocSize, 'ComHookMemBlock');
bCreated := GetLastError <> ERROR_ALREADY_EXISTS;
if (hObjHandle = 0) then
begin
ErrMessage('Could not create file map object');
exit;
end;
{Get a pointer to our process wide memory mapped variable}
lpHookRec := MapViewOfFile(hObjHandle, FILE_MAP_WRITE, 0, 0,
dwAllocSize);
if (lpHookRec = NIL) then
begin
CloseHandle(hObjHandle);
ErrMessage('Could not map file');
exit;
end;
if bCreated then
begin
FillChar(lpHookRec^, dwAllocSize, 0);
end;
end;

procedure UnMapFileMemory;
begin
{Delete our process wide memory mapped variable}
if (lpHookRec <> NIL) then
begin
UnMapViewOfFile(lpHookRec);
lpHookRec := NIL;
end;
if (hObjHandle > 0) then
begin
CloseHandle(hObjHandle);
hObjHandle := 0;
end;
end;

function GetHookRecPointer: PHookRec; stdcall;
begin
{Return a pointer to our process wide memory mapped variable}
result := lpHookRec;
end;

function SysMsgProc(Code : integer;
wParam : integer;
lParam : integer): integer; stdcall;

var
ClassName: string[MAX_CLASS_NAME];
ClassNameLen: integer;
WindowText: string[MAX_WINDOW_TEXT];
WindowTextLen: integer;

procedure GetWindowInfo(Wnd: HWND);
begin
ClassNameLen := Windows.GetClassName(Wnd, @ClassName[1],
MAX_CLASS_NAME);
ClassName[0] := chr(ClassNameLen);
WindowTextLen := Windows.GetWindowText(Wnd, @WindowText[1],
MAX_WINDOW_TEXT);
WindowText[0] := chr(WindowTextLen);
end;

var
Wnd: HWND;
p1, p2: integer;
hChild, hEdit: HWND;
begin
if (code = MSGF_DIALOGBOX) and (PMsg(LParam)^.message = WM_COMMAND)
and (lpHookRec^.ComWindow <> 0) then
begin
Wnd := PMsg(LParam)^.hwnd;
GetWindowInfo(Wnd);

//DebugInfoFmt('SysMsgProc: %x\%x (%s) %s', [GetParent(Wnd),
Wnd, string(ClassName), string(WindowText)]);

if (ClassName = 'WinCOMDialog') and (Pos('WinCOM', WindowText) =
1) then
begin
p1 := Pos(' - ', WindowText);
p2 := Pos(' (', WindowText);
if (p1 <> 0) and (p2 <> 0) then
begin
lpHookRec^.ComUser := Copy(WindowText, p1+3, p2-p1-3);
end
else
begin
hEdit := 0;
hChild := GetWindow(Wnd, GW_CHILD);
repeat
GetWindowInfo(hChild);
if ClassName = 'Edit' then
hEdit := hChild;
hChild := GetWindow(hChild, GW_HWNDNEXT);
until hChild = 0;

if hEdit <> 0 then
PostMessage(lpHookRec^.MainWnd, lpHookRec^.MainMsg,
USERMSG_ACTIVATED, 0);
end;
end;
end;

{Call the next hook in the hook chain}
result := CallNextHookEx(lpHookRec^.SysMsgHook, Code, wParam,
lParam);
end;

function ShellProc(Code : integer;
wParam : integer;
lParam : integer): integer; stdcall;
var
ClassName: string[MAX_CLASS_NAME];
ClassNameLen: integer;
WindowText: string[MAX_WINDOW_TEXT];
WindowTextLen: integer;
begin
case Code of
HSHELL_WINDOWCREATED:
begin
ClassNameLen := GetClassName(wParam, @ClassName[1],
MAX_CLASS_NAME);
ClassName[0] := chr(ClassNameLen);
WindowTextLen := GetWindowText(wParam, @WindowText[1],
MAX_WINDOW_TEXT);
WindowText[0] := chr(WindowTextLen);
//DebugInfoFmt('HSHELL_WINDOWCREATED: %x (%s) %s', [wParam,
string(ClassName), string(WindowText)]);

if (ClassName = 'WinCOM') and (WindowText = 'WinCOM') then
begin
//DebugInfo('... Starting SysMsgHook');
{Set the sysmsg hook and remember our hook handle}
if lpHookRec^.SysMsgHook = 0 then
lpHookRec^.SysMsgHook :=
SetWindowsHookEx(WH_SYSMSGFILTER, @SysMsgProc, hInstance, 0);
lpHookRec^.ComWindow := wParam;
end;
end;
HSHELL_WINDOWDESTROYED:
begin
//DebugInfoFmt('HSHELL_WINDOWDESTROYED: %x', [wParam]);
// If main com window is destroyed, unhook the sysmsg hook
if HWND(wParam) = lpHookRec^.ComWindow then
begin
//DebugInfo('... Stopping SysMsgHook');
if (lpHookRec^.SysMsgHook <> 0) and
(UnHookWindowsHookEx(lpHookRec^.SysMsgHook) <> FALSE) then
lpHookRec^.SysMsgHook := 0;
lpHookRec^.ComWindow := 0;
end;
end;
end; {case code}

{Call the next hook in the hook chain}
result := CallNextHookEx(lpHookRec^.ShellHook, Code, wParam,
lParam);
end;

procedure StartHook; stdcall;
begin
{If we have a process wide memory variable}
{and the hook has not already been set...}
if lpHookRec <> NIL then
begin
if lpHookRec^.ShellHook = 0 then
begin
{Set the hook and remember our hook handle}
lpHookRec^.ShellHook := SetWindowsHookEx(WH_SHELL,
@ShellProc, hInstance, 0);
lpHookRec^.ComWindow := FindWindow('WinCOM', 'WinCOM');
if (lpHookRec^.ComWindow <> 0) and (lpHookRec^.SysMsgHook =
0) then
lpHookRec^.SysMsgHook := SetWindowsHookEx(WH_SYSMSGFILTER,
@SysMsgProc, hInstance, 0);
end;
end;
end;

procedure StopHook; stdcall;
begin
{If we have a process wide memory variable}
{and the hooks has already been set...}
if lpHookRec <> NIL then
begin
{Remove our hooks and clear our hook handles}
if (lpHookRec^.ShellHook <> 0) and
(UnHookWindowsHookEx(lpHookRec^.ShellHook) <> FALSE) then
lpHookRec^.ShellHook := 0;
if (lpHookRec^.SysMsgHook <> 0) and
(UnHookWindowsHookEx(lpHookRec^.SysMsgHook) <> FALSE) then
lpHookRec^.SysMsgHook := 0;
end;
end;

Var
P86Mask: Pointer;

function MaskX86Exceptions: Pointer;
var
dwOldMask: Pointer;
begin
asm
fnstcw WORD PTR dwOldMask;
mov eax, dwOldMask;
or eax, $3f;
mov WORD PTR dwOldMask + 2, ax;
fldcw WORD PTR dwOldMask + 2;
end;
result := dwOldMask;
end;

procedure RestoreX86Mask (dwOldMask: Pointer);
begin
asm
fnclex;
fldcw WORD PTR dwOldMask;
end;
end;

procedure DllEntryPoint(dwReason : DWORD);
begin
case dwReason of
Dll_Process_Attach:
begin
{If we are getting mapped into a process, then get}
{a pointer to our process wide memory mapped variable}
P86Mask := MaskX86Exceptions;
hObjHandle := 0;
lpHookRec := NIL;
MapFileMemory(sizeof(lpHookRec^));
end;
Dll_Process_Detach:
begin
{If we are getting unmapped from a process then, remove}
{the pointer to our process wide memory mapped variable}
UnMapFileMemory;
RestoreX86Mask(P86Mask);
end;
end;
end;

exports
ShellProc,
SysMsgProc,
GetHookRecPointer,
StartHook,
StopHook;

begin
{Set our Dll's main entry point}
DLLProc := @DllEntryPoint;
{Call our Dll's main entry point}
DllEntryPoint(Dll_Process_Attach);
end.

-----------------------------------------------------------------------

unit HookRec;

interface

uses
Windows,
Messages;

const
MAX_CLASS_NAME = 100;
MAX_WINDOW_TEXT = 200;
MAX_USER_NAME = 100;

{Define a record for recording and passing information process wide}
type
PHookRec = ^THookRec;
THookRec = packed record
ShellHook: HHOOK;
SysMsgHook: HHOOK;
MainWnd: HWND;
MainMsg: UINT;
//WatchWindowClass: string[MAX_CLASS_NAME];
//WatchWindowText: string[MAX_WINDOW_TEXT];
ComWindow: HWND;
ComUser: string[MAX_USER_NAME];
end;

const
USERMSG_SHOW = 0;
USERMSG_ACTIVATED = 1;

implementation

end.

0 new messages