2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Window event handlers
5 * FILE: subsystem/win32/win32k/ntuser/event.c
6 * PROGRAMER: James Tabor (james.tabor@rectos.org)
14 typedef struct _EVENTPACK
19 } EVENTPACK
, *PEVENTPACK
;
21 static PEVENTTABLE GlobalEvents
= NULL
;
23 /* PRIVATE FUNCTIONS *********************************************************/
28 GetMaskFromEvent(DWORD Event
)
32 if ( Event
> EVENT_OBJECT_STATECHANGE
)
34 if ( Event
== EVENT_OBJECT_LOCATIONCHANGE
) return SRV_EVENT_LOCATIONCHANGE
;
35 if ( Event
== EVENT_OBJECT_NAMECHANGE
) return SRV_EVENT_NAMECHANGE
;
36 if ( Event
== EVENT_OBJECT_VALUECHANGE
) return SRV_EVENT_VALUECHANGE
;
37 return SRV_EVENT_CREATE
;
40 if ( Event
== EVENT_OBJECT_STATECHANGE
) return SRV_EVENT_STATECHANGE
;
42 Ret
= SRV_EVENT_RUNNING
;
44 if ( Event
< EVENT_SYSTEM_MENUSTART
) return SRV_EVENT_CREATE
;
46 if ( Event
<= EVENT_SYSTEM_MENUPOPUPEND
)
52 if ( Event
<= EVENT_CONSOLE_CARET
-1 ) return SRV_EVENT_CREATE
;
53 if ( Event
<= EVENT_CONSOLE_END_APPLICATION
) return SRV_EVENT_END_APPLICATION
;
54 if ( Event
!= EVENT_OBJECT_FOCUS
) return SRV_EVENT_CREATE
;
62 IntSetSrvEventMask( UINT EventMin
, UINT EventMax
)
65 DPRINT("SetSrvEventMask 1\n");
66 for ( event
= EventMin
; event
<= EventMax
; event
++)
68 if ((event
>= EVENT_SYSTEM_SOUND
&& event
<= EVENT_SYSTEM_MINIMIZEEND
) ||
69 (event
>= EVENT_CONSOLE_CARET
&& event
<= EVENT_CONSOLE_END_APPLICATION
) ||
70 (event
>= EVENT_OBJECT_CREATE
&& event
<= EVENT_OBJECT_ACCELERATORCHANGE
))
72 gpsi
->dwInstalledEventHooks
|= GetMaskFromEvent(event
);
74 if (event
> EVENT_SYSTEM_MINIMIZEEND
&& event
< EVENT_CONSOLE_CARET
)
76 event
= EVENT_CONSOLE_CARET
-1;
77 gpsi
->dwInstalledEventHooks
|= GetMaskFromEvent(event
);
79 if (event
> EVENT_CONSOLE_END_APPLICATION
&& event
< EVENT_OBJECT_CREATE
)
81 event
= EVENT_OBJECT_CREATE
-1;
82 gpsi
->dwInstalledEventHooks
|= GetMaskFromEvent(event
);
84 if (event
> EVENT_OBJECT_ACCELERATORCHANGE
&& event
< EVENT_MAX
)
87 gpsi
->dwInstalledEventHooks
|= GetMaskFromEvent(event
);
91 if (!gpsi
->dwInstalledEventHooks
)
92 gpsi
->dwInstalledEventHooks
|= SRV_EVENT_RUNNING
; // Set something.
93 DPRINT("SetSrvEventMask 2 : %x\n", gpsi
->dwInstalledEventHooks
);
99 IntCallLowLevelEvent( PEVENTHOOK pEH
,
110 EP
.idObject
= idObject
;
111 EP
.idChild
= idChild
;
113 /* FIXME should get timeout from
114 * HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */
115 Status
= co_MsqSendMessage( pEH
->head
.pti
->MessageQueue
,
125 return NT_SUCCESS(Status
) ? uResult
: 0;
132 IntRemoveEvent(PEVENTHOOK pEH
)
136 DPRINT("IntRemoveEvent pEH 0x%x\n",pEH
);
137 KeEnterCriticalRegion();
138 RemoveEntryList(&pEH
->Chain
);
139 GlobalEvents
->Counts
--;
140 if (!GlobalEvents
->Counts
) gpsi
->dwInstalledEventHooks
= 0;
141 UserDeleteObject(UserHMGetHandle(pEH
), otEvent
);
142 KeLeaveCriticalRegion();
148 /* FUNCTIONS *****************************************************************/
152 co_EVENT_CallEvents( DWORD event
,
159 PEVENTPACK pEP
= (PEVENTPACK
)idChild
;
163 Result
= co_IntCallEventProc( UserHMGetHandle(pEH
),
168 (DWORD_PTR
)(NtCurrentTeb()->ClientId
).UniqueThread
,
169 (DWORD
)EngGetTickCount(),
186 DPRINT("IntNotifyWinEvent GlobalEvents = 0x%x pWnd 0x%x\n",GlobalEvents
, pWnd
);
190 if (pWnd
&& pWnd
->state
& WNDS_DESTROYED
) return;
192 if (!GlobalEvents
|| !GlobalEvents
->Counts
) return;
194 pLE
= GlobalEvents
->Events
.Flink
;
195 pEH
= CONTAINING_RECORD(pLE
, EVENTHOOK
, Chain
);
198 UserReferenceObject(pEH
);
199 // Must be inside the event window.
200 if ( (pEH
->eventMin
<= Event
) && (pEH
->eventMax
>= Event
))
202 if (pEH
->head
.pti
->pEThread
!= PsGetCurrentThread())
203 { // if all process || all thread || other thread same process
204 if (!(pEH
->idProcess
) || !(pEH
->idThread
) ||
205 (NtCurrentTeb()->ClientId
.UniqueProcess
== (PVOID
)(DWORD_PTR
)pEH
->idProcess
))
207 Result
= IntCallLowLevelEvent( pEH
,
209 UserHMGetHandle(pWnd
),
213 }// if ^skip own thread && ((Pid && CPid == Pid && ^skip own process) || all process)
214 else if ( !(pEH
->Flags
& WINEVENT_SKIPOWNTHREAD
) &&
215 ( ((pEH
->idProcess
&&
216 NtCurrentTeb()->ClientId
.UniqueProcess
== (PVOID
)(DWORD_PTR
)pEH
->idProcess
) &&
217 !(pEH
->Flags
& WINEVENT_SKIPOWNPROCESS
)) ||
220 Result
= co_IntCallEventProc( UserHMGetHandle(pEH
),
222 UserHMGetHandle(pWnd
),
225 PtrToUint(NtCurrentTeb()->ClientId
.UniqueThread
),
226 (DWORD
)EngGetTickCount(),
230 UserDereferenceObject(pEH
);
231 pLE
= pEH
->Chain
.Flink
;
232 pEH
= CONTAINING_RECORD(pLE
, EVENTHOOK
, Chain
);
233 } while (pLE
!= &GlobalEvents
->Events
);
238 NtUserNotifyWinEvent(
244 PWINDOW_OBJECT Window
= NULL
;
245 USER_REFERENCE_ENTRY Ref
;
246 UserEnterExclusive();
249 if (hWnd
&& (hWnd
!= INVALID_HANDLE_VALUE
) && !(Window
= UserGetWindowObject(hWnd
)))
255 if (gpsi
->dwInstalledEventHooks
& GetMaskFromEvent(Event
))
257 UserRefObjectCo(Window
, &Ref
);
258 IntNotifyWinEvent( Event
, Window
->Wnd
, idObject
, idChild
);
259 UserDerefObjectCo(Window
);
266 NtUserSetWinEventHook(
269 HMODULE hmodWinEventProc
,
270 PUNICODE_STRING puString
,
271 WINEVENTPROC lpfnWinEventProc
,
277 HWINEVENTHOOK Ret
= NULL
;
280 PETHREAD Thread
= NULL
;
282 DPRINT("NtUserSetWinEventHook hmod 0x%x, pfn 0x%x\n",hmodWinEventProc
, lpfnWinEventProc
);
284 UserEnterExclusive();
288 GlobalEvents
= ExAllocatePoolWithTag(PagedPool
, sizeof(EVENTTABLE
), TAG_HOOK
);
289 if (GlobalEvents
== NULL
)
291 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
294 GlobalEvents
->Counts
= 0;
295 InitializeListHead(&GlobalEvents
->Events
);
298 if (eventMin
> eventMax
)
300 SetLastWin32Error(ERROR_INVALID_HOOK_FILTER
);
304 if (!lpfnWinEventProc
)
306 SetLastWin32Error(ERROR_INVALID_FILTER_PROC
);
310 if ((dwflags
& WINEVENT_INCONTEXT
) && !hmodWinEventProc
)
312 SetLastWin32Error(ERROR_HOOK_NEEDS_HMOD
);
318 Status
= PsLookupThreadByThreadId((HANDLE
)(DWORD_PTR
)idThread
, &Thread
);
319 if (!NT_SUCCESS(Status
))
321 SetLastWin32Error(ERROR_INVALID_THREAD_ID
);
326 pEH
= UserCreateObject(gHandleTable
, NULL
, &Handle
, otEvent
, sizeof(EVENTHOOK
));
329 InsertTailList(&GlobalEvents
->Events
, &pEH
->Chain
);
330 GlobalEvents
->Counts
++;
332 UserHMGetHandle(pEH
) = Handle
;
334 pEH
->head
.pti
= Thread
->Tcb
.Win32Thread
;
336 pEH
->head
.pti
= GetW32ThreadInfo();
337 pEH
->eventMin
= eventMin
;
338 pEH
->eventMax
= eventMax
;
339 pEH
->idProcess
= idProcess
;
340 pEH
->idThread
= idThread
;
341 pEH
->Flags
= dwflags
;
343 if (NULL
!= hmodWinEventProc
)
345 pEH
->offPfn
= (ULONG_PTR
)((char *)lpfnWinEventProc
- (char *)hmodWinEventProc
);
346 pEH
->ihmod
= (INT
)hmodWinEventProc
;
347 pEH
->Proc
= lpfnWinEventProc
;
350 pEH
->Proc
= lpfnWinEventProc
;
352 UserDereferenceObject(pEH
);
355 IntSetSrvEventMask( eventMin
, eventMax
);
359 if (Thread
) ObDereferenceObject(Thread
);
366 NtUserUnhookWinEvent(
367 HWINEVENTHOOK hWinEventHook
)
372 UserEnterExclusive();
374 pEH
= (PEVENTHOOK
)UserGetObject(gHandleTable
, hWinEventHook
, otEvent
);
377 Ret
= IntRemoveEvent(pEH
);