2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Window event handlers
5 * FILE: win32ss/user/ntuser/event.c
6 * PROGRAMER: James Tabor (james.tabor@rectos.org)
10 DBG_DEFAULT_CHANNEL(UserEvent
);
12 typedef struct _EVENTPACK
18 } EVENTPACK
, *PEVENTPACK
;
20 static PEVENTTABLE GlobalEvents
= NULL
;
22 /* PRIVATE FUNCTIONS *********************************************************/
27 GetMaskFromEvent(DWORD Event
)
31 if ( Event
> EVENT_OBJECT_STATECHANGE
)
33 if ( Event
== EVENT_OBJECT_LOCATIONCHANGE
) return SRV_EVENT_LOCATIONCHANGE
;
34 if ( Event
== EVENT_OBJECT_NAMECHANGE
) return SRV_EVENT_NAMECHANGE
;
35 if ( Event
== EVENT_OBJECT_VALUECHANGE
) return SRV_EVENT_VALUECHANGE
;
36 return SRV_EVENT_CREATE
;
39 if ( Event
== EVENT_OBJECT_STATECHANGE
) return SRV_EVENT_STATECHANGE
;
41 Ret
= SRV_EVENT_RUNNING
;
43 if ( Event
< EVENT_SYSTEM_MENUSTART
) return SRV_EVENT_CREATE
;
45 if ( Event
<= EVENT_SYSTEM_MENUPOPUPEND
)
51 if ( Event
<= EVENT_CONSOLE_CARET
-1 ) return SRV_EVENT_CREATE
;
52 if ( Event
<= EVENT_CONSOLE_END_APPLICATION
) return SRV_EVENT_END_APPLICATION
;
53 if ( Event
!= EVENT_OBJECT_FOCUS
) return SRV_EVENT_CREATE
;
61 IntSetSrvEventMask( UINT EventMin
, UINT EventMax
)
64 TRACE("SetSrvEventMask 1\n");
65 for ( event
= EventMin
; event
<= EventMax
; event
++)
67 if ((event
>= EVENT_SYSTEM_SOUND
&& event
<= EVENT_SYSTEM_MINIMIZEEND
) ||
68 (event
>= EVENT_CONSOLE_CARET
&& event
<= EVENT_CONSOLE_END_APPLICATION
) ||
69 (event
>= EVENT_OBJECT_CREATE
&& event
<= EVENT_OBJECT_ACCELERATORCHANGE
))
71 gpsi
->dwInstalledEventHooks
|= GetMaskFromEvent(event
);
73 if (event
> EVENT_SYSTEM_MINIMIZEEND
&& event
< EVENT_CONSOLE_CARET
)
75 event
= EVENT_CONSOLE_CARET
-1;
76 gpsi
->dwInstalledEventHooks
|= GetMaskFromEvent(event
);
78 if (event
> EVENT_CONSOLE_END_APPLICATION
&& event
< EVENT_OBJECT_CREATE
)
80 event
= EVENT_OBJECT_CREATE
-1;
81 gpsi
->dwInstalledEventHooks
|= GetMaskFromEvent(event
);
83 if (event
> EVENT_OBJECT_ACCELERATORCHANGE
&& event
< EVENT_MAX
)
86 gpsi
->dwInstalledEventHooks
|= GetMaskFromEvent(event
);
90 if (!gpsi
->dwInstalledEventHooks
)
91 gpsi
->dwInstalledEventHooks
|= SRV_EVENT_RUNNING
; // Set something.
92 TRACE("SetSrvEventMask 2 : %x\n", gpsi
->dwInstalledEventHooks
);
98 IntCallLowLevelEvent( PEVENTHOOK pEH
,
108 pEP
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(EVENTPACK
), TAG_HOOK
);
112 pEP
->idObject
= idObject
;
113 pEP
->idChild
= idChild
;
114 pEP
->idThread
= idThread
;
119 Msg
.lParam
= POSTEVENT_NWE
;
122 MsqPostMessage(pEH
->head
.pti
, &Msg
, FALSE
, QS_EVENT
, POSTEVENT_NWE
, (LONG_PTR
)pEP
);
127 IntRemoveEvent(PVOID Object
)
129 PEVENTHOOK pEH
= Object
;
132 TRACE("IntRemoveEvent pEH %p\n", pEH
);
133 KeEnterCriticalRegion();
134 RemoveEntryList(&pEH
->Chain
);
135 GlobalEvents
->Counts
--;
136 if (!GlobalEvents
->Counts
) gpsi
->dwInstalledEventHooks
= 0;
137 UserDeleteObject(UserHMGetHandle(pEH
), TYPE_WINEVENTHOOK
);
138 KeLeaveCriticalRegion();
144 /* FUNCTIONS *****************************************************************/
147 // Dispatch MsgQueue Event Call processor!
151 co_EVENT_CallEvents( DWORD event
,
158 PEVENTPACK pEP
= (PEVENTPACK
)idChild
;
161 TRACE("Dispatch Event 0x%lx, idObject %uI hwnd %p\n", event
, idObject
, hwnd
);
162 Result
= co_IntCallEventProc( UserHMGetHandle(pEH
),
168 (DWORD
)EngGetTickCount(),
173 ExFreePoolWithTag(pEP
, TAG_HOOK
);
187 PLIST_ENTRY ListEntry
;
188 PTHREADINFO pti
, ptiCurrent
;
189 USER_REFERENCE_ENTRY Ref
;
191 TRACE("IntNotifyWinEvent GlobalEvents = %p pWnd %p\n", GlobalEvents
, pWnd
);
193 if (!GlobalEvents
|| !GlobalEvents
->Counts
) return;
195 if (pWnd
&& pWnd
->state
& WNDS_DESTROYED
) return;
197 ptiCurrent
= PsGetCurrentThreadWin32Thread();
199 if (pWnd
&& flags
& WEF_SETBYWNDPTI
)
200 pti
= pWnd
->head
.pti
;
204 ListEntry
= GlobalEvents
->Events
.Flink
;
205 ASSERT(ListEntry
!= &GlobalEvents
->Events
);
206 while (ListEntry
!= &GlobalEvents
->Events
)
208 pEH
= CONTAINING_RECORD(ListEntry
, EVENTHOOK
, Chain
);
209 ListEntry
= ListEntry
->Flink
;
211 // Must be inside the event window.
212 if ( Event
>= pEH
->eventMin
&& Event
<= pEH
->eventMax
)
214 // if all process || all thread || other thread same process
215 // if ^skip own thread && ((Pid && CPid == Pid && ^skip own process) || all process)
216 if (!( (pEH
->idProcess
&& pEH
->idProcess
!= PtrToUint(pti
->pEThread
->Cid
.UniqueProcess
)) ||
217 (pEH
->Flags
& WINEVENT_SKIPOWNPROCESS
&& pEH
->head
.pti
->ppi
== pti
->ppi
) ||
218 (pEH
->idThread
&& pEH
->idThread
!= PtrToUint(pti
->pEThread
->Cid
.UniqueThread
)) ||
219 (pEH
->Flags
& WINEVENT_SKIPOWNTHREAD
&& pEH
->head
.pti
== pti
) ||
220 pEH
->head
.pti
->rpdesk
!= ptiCurrent
->rpdesk
) ) // Same as hooks.
222 UserRefObjectCo(pEH
, &Ref
);
223 if (pEH
->Flags
& WINEVENT_INCONTEXT
)
225 TRACE("In Event 0x%x, idObject %d hwnd %p\n", Event
, idObject
, pWnd
? UserHMGetHandle(pWnd
) : NULL
);
226 co_IntCallEventProc( UserHMGetHandle(pEH
),
228 pWnd
? UserHMGetHandle(pWnd
) : NULL
,
231 PtrToUint(NtCurrentTeb()->ClientId
.UniqueThread
),
232 (DWORD
)EngGetTickCount(),
239 TRACE("Out Event 0x%x, idObject %d hwnd %p\n", Event
, idObject
, pWnd
? UserHMGetHandle(pWnd
) : NULL
);
240 IntCallLowLevelEvent( pEH
,
242 pWnd
? UserHMGetHandle(pWnd
) : NULL
,
245 PtrToUint(NtCurrentTeb()->ClientId
.UniqueThread
));
247 UserDerefObjectCo(pEH
);
255 NtUserNotifyWinEvent(
262 USER_REFERENCE_ENTRY Ref
;
263 UserEnterExclusive();
266 if (hWnd
&& (hWnd
!= INVALID_HANDLE_VALUE
))
268 Window
= UserGetWindowObject(hWnd
);
276 if (gpsi
->dwInstalledEventHooks
& GetMaskFromEvent(Event
))
278 if (Window
) UserRefObjectCo(Window
, &Ref
);
279 IntNotifyWinEvent( Event
, Window
, idObject
, idChild
, WEF_SETBYWNDPTI
);
280 if (Window
) UserDerefObjectCo(Window
);
287 NtUserSetWinEventHook(
290 HMODULE hmodWinEventProc
,
291 PUNICODE_STRING puString
,
292 WINEVENTPROC lpfnWinEventProc
,
298 HWINEVENTHOOK Ret
= NULL
;
303 TRACE("NtUserSetWinEventHook hmod %p, pfn %p\n", hmodWinEventProc
, lpfnWinEventProc
);
305 UserEnterExclusive();
309 GlobalEvents
= ExAllocatePoolWithTag(PagedPool
, sizeof(EVENTTABLE
), TAG_HOOK
);
310 if (GlobalEvents
== NULL
)
312 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
315 GlobalEvents
->Counts
= 0;
316 InitializeListHead(&GlobalEvents
->Events
);
319 if (eventMin
> eventMax
)
321 EngSetLastError(ERROR_INVALID_HOOK_FILTER
);
325 if (!lpfnWinEventProc
)
327 EngSetLastError(ERROR_INVALID_FILTER_PROC
);
331 if (dwflags
& WINEVENT_INCONTEXT
)
333 if (!hmodWinEventProc
)
335 ERR("Hook needs a module\n");
336 EngSetLastError(ERROR_HOOK_NEEDS_HMOD
);
339 if (puString
== NULL
)
341 ERR("Dll not found\n");
342 EngSetLastError(ERROR_DLL_NOT_FOUND
);
348 TRACE("Out of Context\n");
349 hmodWinEventProc
= 0;
355 Status
= PsLookupThreadByThreadId((HANDLE
)(DWORD_PTR
)idThread
, &Thread
);
356 if (!NT_SUCCESS(Status
))
358 EngSetLastError(ERROR_INVALID_THREAD_ID
);
361 pti
= PsGetThreadWin32Thread(Thread
);
362 ObDereferenceObject(Thread
);
366 pti
= PsGetCurrentThreadWin32Thread();
368 // Creator, pti is set here.
369 pEH
= UserCreateObject(gHandleTable
, NULL
, pti
, &Handle
, TYPE_WINEVENTHOOK
, sizeof(EVENTHOOK
));
372 InsertTailList(&GlobalEvents
->Events
, &pEH
->Chain
);
373 GlobalEvents
->Counts
++;
375 UserHMGetHandle(pEH
) = Handle
;
376 pEH
->eventMin
= eventMin
;
377 pEH
->eventMax
= eventMax
;
378 pEH
->idProcess
= idProcess
; // These are cmp'ed
379 pEH
->idThread
= idThread
; // "
380 pEH
->Flags
= dwflags
;
382 If WINEVENT_INCONTEXT, set offset from hmod and proc. Save ihmod from
383 the atom index table where the hmod data is saved to be recalled later
384 if fSync set by WINEVENT_INCONTEXT.
385 If WINEVENT_OUTOFCONTEXT just use proc..
388 if (hmodWinEventProc
!= NULL
)
390 pEH
->offPfn
= (ULONG_PTR
)((char *)lpfnWinEventProc
- (char *)hmodWinEventProc
);
391 pEH
->ihmod
= (INT_PTR
)hmodWinEventProc
;
392 pEH
->Proc
= lpfnWinEventProc
;
396 pEH
->Proc
= lpfnWinEventProc
;
398 pEH
->ihmod
= (INT_PTR
)hmodWinEventProc
;
401 UserDereferenceObject(pEH
);
404 IntSetSrvEventMask( eventMin
, eventMax
);
414 NtUserUnhookWinEvent(
415 HWINEVENTHOOK hWinEventHook
)
420 UserEnterExclusive();
422 pEH
= (PEVENTHOOK
)UserGetObject(gHandleTable
, hWinEventHook
, TYPE_WINEVENTHOOK
);
425 Ret
= IntRemoveEvent(pEH
);