summaryrefslogtreecommitdiff
path: root/plugins/Actman/hooks/i_hook.inc
blob: 7bdf64fd474a82c9600310ed95af0dfce56fe677 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
{}

const
  HWND_MESSAGE = HWND(-3);
const
  ACF_ASSIGNED = $80000000;  // hook assigned
  ACF_DISABLED = $10000000;  // hook disabled
const
  WM_RESETHOOKS = WM_USER+1312;
  WM_FIRSTHOOK  = WM_USER+1313;
  WM_LASTHOOK   = WM_FIRSTHOOK+1000;

type
  pHookRec = ^tHookRec;
  tHookRec = record
    flags  :dword;
    name   :PAnsiChar; // name for hook
    handle :THANDLE;   // handle of hook
    descr  :PWideChar; // name for list
    action :dword;     // assigned action
    message:uint;      // window message for hook
  end;
  pHookList = ^tHookList;
  tHookList  = array [0..1023] of tHookRec;

var
  HookList:pHookList = nil;
  MaxHooks:integer = 0;
  MessageWindow:HWND = 0;

function GetNextMessage:uint;
var
  i:uint;
  j:integer;
begin
  result:=0;
  for i:=WM_FIRSTHOOK to WM_LASTHOOK do
  begin
    for j:=0 to MaxHooks-1 do
    begin
      with HookList^[j] do
      begin
        if ((flags and ACF_ASSIGNED)<>0) and (i=message) then
        begin
          inc(result);
          break;
        end;
      end;
    end;
    if result=0 then
    begin
      result:=i;
      break;
    end
    else
      result:=0;
  end;
end;

procedure SetAllHooks;
var
  i:integer;
  msg:cardinal;
begin
  msg:=WM_FIRSTHOOK;
  for i:=0 to MaxHooks-1 do
  begin
    with HookList[i] do
    begin
      message:=msg;
      if (flags and ACF_ASSIGNED)<>0 then
      begin
        if (flags and ACF_DISABLED)<>0 then
        begin
          if handle<>0 then
          begin
            UnhookEvent(handle);
            handle:=0;
          end;
        end
        else
        begin
          if handle<>0 then
            UnhookEvent(handle);
          handle:=HookEventMessage(name,MessageWindow,message);
        end;
      end;
    end;
    inc(msg);
  end;
end;

function GetHookByMessage(msg:uint):pHookRec;
var
  i:integer;
begin
  result:=nil;
  for i:=0 to MaxHooks-1 do
  begin
    with HookList[i] do
    begin
      if ((flags and ACF_ASSIGNED)<>0) and (msg=message) then
      begin
        result:=@HookList[i];
        break;
      end;
    end;
  end;
end;

function HookWndProc(Dialog:HWND;hMessage:uint;wParam:WPARAM;lParam:LPARAM):LRESULT; stdcall;
var
  p:pHookRec;
  ap:tAct_Param;
begin
  result:=0;
  case hMessage of
    WM_FIRSTHOOK..WM_LASTHOOK: begin
      p:=GetHookByMessage(hMessage);
      if p<>nil then
      begin
        ap.flags :=ACTP_WAIT;
        ap.Id    :=p^.action;
        ap.wParam:=wParam;
        ap.lParam:=lParam;
        result:=CallService(MS_ACT_RUNPARAMS,0,TLPARAM(@ap));
      end;
    end;
  else
    result:=DefWindowProc(Dialog,hMessage,wParam,lParam);
  end;
end;

procedure ClearHooks;
var
  i:integer;
begin
  for i:=0 to MaxHooks-1 do
  begin
    with HookList[i] do
    begin
      if (flags and ACF_ASSIGNED)<>0 then
      begin
        mFreeMem(descr);
        mFreeMem(name);
        if handle<>0 then
          UnhookEvent(handle);
      end;
    end;
  end;
  FreeMem(HookList);
  MaxHooks:=0;
end;