Where to find a code example using:
* SetWindowsHookEx
* ShellProc
Thankful,
Paulo Cordeiro
pauloc...@cids.com.br
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.