ReactOS  0.4.11-dev-791-gf6f1255
event.c
Go to the documentation of this file.
1 /*
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)
7  */
8 
9 #include <win32k.h>
10 DBG_DEFAULT_CHANNEL(UserEvent);
11 
12 typedef struct _EVENTPACK
13 {
19 
21 
22 /* PRIVATE FUNCTIONS *********************************************************/
23 
24 static
25 DWORD
28 {
29  DWORD Ret = 0;
30 
31  if ( Event > EVENT_OBJECT_STATECHANGE )
32  {
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;
37  }
38 
39  if ( Event == EVENT_OBJECT_STATECHANGE ) return SRV_EVENT_STATECHANGE;
40 
41  Ret = SRV_EVENT_RUNNING;
42 
43  if ( Event < EVENT_SYSTEM_MENUSTART ) return SRV_EVENT_CREATE;
44 
45  if ( Event <= EVENT_SYSTEM_MENUPOPUPEND )
46  {
47  Ret = SRV_EVENT_MENU;
48  }
49  else
50  {
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;
54  }
55  return Ret;
56 }
57 
58 static
59 VOID
61 IntSetSrvEventMask( UINT EventMin, UINT EventMax)
62 {
63  UINT event;
64  TRACE("SetSrvEventMask 1\n");
65  for ( event = EventMin; event <= EventMax; event++)
66  {
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))
70  {
72  }
73  if (event > EVENT_SYSTEM_MINIMIZEEND && event < EVENT_CONSOLE_CARET)
74  {
75  event = EVENT_CONSOLE_CARET-1;
77  }
78  if (event > EVENT_CONSOLE_END_APPLICATION && event < EVENT_OBJECT_CREATE )
79  {
80  event = EVENT_OBJECT_CREATE-1;
82  }
83  if (event > EVENT_OBJECT_ACCELERATORCHANGE && event < EVENT_MAX)
84  {
85  event = EVENT_MAX-1;
87  break;
88  }
89  }
91  gpsi->dwInstalledEventHooks |= SRV_EVENT_RUNNING; // Set something.
92  TRACE("SetSrvEventMask 2 : %x\n", gpsi->dwInstalledEventHooks);
93 }
94 
95 static
96 LRESULT
99  DWORD event,
100  HWND hwnd,
101  LONG idObject,
102  LONG idChild,
103  LONG idThread)
104 {
105  PEVENTPACK pEP;
106  MSG Msg;
107 
109  if (!pEP) return 0;
110 
111  pEP->pEH = pEH;
112  pEP->idObject = idObject;
113  pEP->idChild = idChild;
114  pEP->idThread = idThread;
115 
116  Msg.message = event;
117  Msg.hwnd = hwnd;
118  Msg.wParam = 0;
119  Msg.lParam = POSTEVENT_NWE;
120  Msg.time = 0;
121 
123  return 0;
124 }
125 
126 BOOLEAN
128 {
129  PEVENTHOOK pEH = Object;
130  if (pEH)
131  {
132  TRACE("IntRemoveEvent pEH %p\n", pEH);
134  RemoveEntryList(&pEH->Chain);
135  GlobalEvents->Counts--;
136  if (!GlobalEvents->Counts) gpsi->dwInstalledEventHooks = 0;
139  return TRUE;
140  }
141  return FALSE;
142 }
143 
144 /* FUNCTIONS *****************************************************************/
145 
146 //
147 // Dispatch MsgQueue Event Call processor!
148 //
149 LRESULT
150 APIENTRY
152  HWND hwnd,
153  UINT_PTR idObject,
154  LONG_PTR idChild)
155 {
156  PEVENTHOOK pEH;
157  LRESULT Result;
158  PEVENTPACK pEP = (PEVENTPACK)idChild;
159 
160  pEH = pEP->pEH;
161  TRACE("Dispatch Event 0x%lx, idObject %uI hwnd %p\n", event, idObject, hwnd);
162  Result = co_IntCallEventProc( UserHMGetHandle(pEH),
163  event,
164  hwnd,
165  pEP->idObject,
166  pEP->idChild,
167  pEP->idThread,
169  pEH->Proc,
170  pEH->ihmod,
171  pEH->offPfn);
172 
174  return Result;
175 }
176 
177 VOID
178 FASTCALL
180  DWORD Event,
181  PWND pWnd,
182  LONG idObject,
183  LONG idChild,
184  DWORD flags)
185 {
186  PEVENTHOOK pEH;
187  PLIST_ENTRY ListEntry;
188  PTHREADINFO pti, ptiCurrent;
190 
191  TRACE("IntNotifyWinEvent GlobalEvents = %p pWnd %p\n", GlobalEvents, pWnd);
192 
193  if (!GlobalEvents || !GlobalEvents->Counts) return;
194 
195  if (pWnd && pWnd->state & WNDS_DESTROYED) return;
196 
197  ptiCurrent = PsGetCurrentThreadWin32Thread();
198 
199  if (pWnd && flags & WEF_SETBYWNDPTI)
200  pti = pWnd->head.pti;
201  else
202  pti = ptiCurrent;
203 
204  ListEntry = GlobalEvents->Events.Flink;
205  ASSERT(ListEntry != &GlobalEvents->Events);
206  while (ListEntry != &GlobalEvents->Events)
207  {
208  pEH = CONTAINING_RECORD(ListEntry, EVENTHOOK, Chain);
209  ListEntry = ListEntry->Flink;
210 
211  // Must be inside the event window.
212  if ( Event >= pEH->eventMin && Event <= pEH->eventMax )
213  {
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.
221  {
222  UserRefObjectCo(pEH, &Ref);
223  if (pEH->Flags & WINEVENT_INCONTEXT)
224  {
225  TRACE("In Event 0x%x, idObject %d hwnd %p\n", Event, idObject, pWnd ? UserHMGetHandle(pWnd) : NULL);
227  Event,
228  pWnd ? UserHMGetHandle(pWnd) : NULL,
229  idObject,
230  idChild,
233  pEH->Proc,
234  pEH->ihmod,
235  pEH->offPfn);
236  }
237  else
238  {
239  TRACE("Out Event 0x%x, idObject %d hwnd %p\n", Event, idObject, pWnd ? UserHMGetHandle(pWnd) : NULL);
241  Event,
242  pWnd ? UserHMGetHandle(pWnd) : NULL,
243  idObject,
244  idChild,
246  }
247  UserDerefObjectCo(pEH);
248  }
249  }
250  }
251 }
252 
253 VOID
254 APIENTRY
256  DWORD Event,
257  HWND hWnd,
258  LONG idObject,
259  LONG idChild)
260 {
261  PWND Window = NULL;
264 
265  /* Validate input */
266  if (hWnd && (hWnd != INVALID_HANDLE_VALUE))
267  {
268  Window = UserGetWindowObject(hWnd);
269  if (!Window)
270  {
271  UserLeave();
272  return;
273  }
274  }
275 
277  {
278  if (Window) UserRefObjectCo(Window, &Ref);
279  IntNotifyWinEvent( Event, Window, idObject, idChild, WEF_SETBYWNDPTI);
280  if (Window) UserDerefObjectCo(Window);
281  }
282  UserLeave();
283 }
284 
286 APIENTRY
288  UINT eventMin,
289  UINT eventMax,
290  HMODULE hmodWinEventProc,
291  PUNICODE_STRING puString,
292  WINEVENTPROC lpfnWinEventProc,
293  DWORD idProcess,
294  DWORD idThread,
295  UINT dwflags)
296 {
297  PEVENTHOOK pEH;
298  HWINEVENTHOOK Ret = NULL;
300  HANDLE Handle;
301  PTHREADINFO pti;
302 
303  TRACE("NtUserSetWinEventHook hmod %p, pfn %p\n", hmodWinEventProc, lpfnWinEventProc);
304 
306 
307  if ( !GlobalEvents )
308  {
309  GlobalEvents = ExAllocatePoolWithTag(PagedPool, sizeof(EVENTTABLE), TAG_HOOK);
310  if (GlobalEvents == NULL)
311  {
313  goto SetEventExit;
314  }
315  GlobalEvents->Counts = 0;
316  InitializeListHead(&GlobalEvents->Events);
317  }
318 
319  if (eventMin > eventMax)
320  {
322  goto SetEventExit;
323  }
324 
325  if (!lpfnWinEventProc)
326  {
328  goto SetEventExit;
329  }
330 
331  if (dwflags & WINEVENT_INCONTEXT)
332  {
333  if (!hmodWinEventProc)
334  {
335  ERR("Hook needs a module\n");
337  goto SetEventExit;
338  }
339  if (puString == NULL)
340  {
341  ERR("Dll not found\n");
343  goto SetEventExit;
344  }
345  }
346  else
347  {
348  TRACE("Out of Context\n");
349  hmodWinEventProc = 0;
350  }
351 
352  if (idThread)
353  {
355  Status = PsLookupThreadByThreadId((HANDLE)(DWORD_PTR)idThread, &Thread);
356  if (!NT_SUCCESS(Status))
357  {
359  goto SetEventExit;
360  }
361  pti = PsGetThreadWin32Thread(Thread);
362  ObDereferenceObject(Thread);
363  }
364  else
365  {
367  }
368  // Creator, pti is set here.
369  pEH = UserCreateObject(gHandleTable, NULL, pti, &Handle, TYPE_WINEVENTHOOK, sizeof(EVENTHOOK));
370  if (pEH)
371  {
372  InsertTailList(&GlobalEvents->Events, &pEH->Chain);
373  GlobalEvents->Counts++;
374 
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;
381  /*
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..
386  Do this instead....
387  */
388  if (hmodWinEventProc != NULL)
389  {
390  pEH->offPfn = (ULONG_PTR)((char *)lpfnWinEventProc - (char *)hmodWinEventProc);
391  pEH->ihmod = (INT_PTR)hmodWinEventProc;
392  pEH->Proc = lpfnWinEventProc;
393  }
394  else
395  {
396  pEH->Proc = lpfnWinEventProc;
397  pEH->offPfn = 0;
398  pEH->ihmod = (INT_PTR)hmodWinEventProc;
399  }
400 
402 
403  Ret = Handle;
404  IntSetSrvEventMask( eventMin, eventMax);
405  }
406 
407 SetEventExit:
408  UserLeave();
409  return Ret;
410 }
411 
412 BOOL
413 APIENTRY
415  HWINEVENTHOOK hWinEventHook)
416 {
417  PEVENTHOOK pEH;
418  BOOL Ret = FALSE;
419 
421 
422  pEH = (PEVENTHOOK)UserGetObject(gHandleTable, hWinEventHook, TYPE_WINEVENTHOOK);
423  if (pEH)
424  {
425  Ret = IntRemoveEvent(pEH);
426  }
427 
428  UserLeave();
429  return Ret;
430 }
431 
432 /* EOF */
DWORD *typedef PVOID
Definition: winlogon.h:61
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
PVOID NTAPI PsGetThreadWin32Thread(IN PETHREAD Thread)
Definition: thread.c:795
#define PtrToUint(p)
Definition: basetsd.h:85
UINT Counts
Definition: hook.h:32
BOOL FASTCALL UserDeleteObject(HANDLE h, HANDLE_TYPE type)
Definition: object.c:683
#define TRUE
Definition: types.h:120
struct @1570 Msg[]
INT_PTR ihmod
Definition: hook.h:26
#define WINEVENT_SKIPOWNPROCESS
Definition: winable.h:34
#define TAG_HOOK
Definition: tags.h:5
LIST_ENTRY Events
Definition: hook.h:31
BOOL APIENTRY NtUserUnhookWinEvent(HWINEVENTHOOK hWinEventHook)
Definition: event.c:414
HWINEVENTHOOK APIENTRY NtUserSetWinEventHook(UINT eventMin, UINT eventMax, HMODULE hmodWinEventProc, PUNICODE_STRING puString, WINEVENTPROC lpfnWinEventProc, DWORD idProcess, DWORD idThread, UINT dwflags)
Definition: event.c:287
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
THROBJHEAD head
Definition: hook.h:17
NTSTATUS NTAPI PsLookupThreadByThreadId(IN HANDLE ThreadId, OUT PETHREAD *Thread)
Definition: thread.c:643
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1827
VOID FASTCALL IntNotifyWinEvent(DWORD Event, PWND pWnd, LONG idObject, LONG idChild, DWORD flags)
Definition: event.c:179
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:805
HWND hWnd
Definition: settings.c:17
#define ERROR_INVALID_THREAD_ID
Definition: winerror.h:925
static __inline VOID UserRefObjectCo(PVOID obj, PUSER_REFERENCE_ENTRY UserReferenceEntry)
Definition: object.h:25
HANDLE HWND
Definition: compat.h:13
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
static DWORD FASTCALL GetMaskFromEvent(DWORD Event)
Definition: event.c:27
VOID(CALLBACK * WINEVENTPROC)(HWINEVENTHOOK, DWORD, HWND, LONG, LONG, DWORD, DWORD)
Definition: winable.h:68
BOOL FASTCALL UserDereferenceObject(PVOID Object)
Definition: object.c:610
#define ERROR_DLL_NOT_FOUND
Definition: winerror.h:679
#define SRV_EVENT_STATECHANGE
Definition: ntuser.h:1039
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
int32_t INT_PTR
Definition: typedefs.h:62
#define InsertTailList(ListHead, Entry)
LRESULT APIENTRY co_EVENT_CallEvents(DWORD event, HWND hwnd, UINT_PTR idObject, LONG_PTR idChild)
Definition: event.c:151
static HWINEVENTHOOK(WINAPI *pSetWinEventHook)(DWORD
#define FASTCALL
Definition: nt_native.h:50
struct _DESKTOP * rpdesk
Definition: win32.h:91
PSERVERINFO gpsi
Definition: main.c:27
DWORD DWORD
Definition: winlogon.h:84
LONG idObject
Definition: event.c:15
PVOID FASTCALL UserCreateObject(PUSER_HANDLE_TABLE ht, PDESKTOP pDesktop, PTHREADINFO pti, HANDLE *h, HANDLE_TYPE type, ULONG size)
Definition: object.c:535
PPROCESSINFO ppi
Definition: win32.h:87
static LRESULT FASTCALL IntCallLowLevelEvent(PEVENTHOOK pEH, DWORD event, HWND hwnd, LONG idObject, LONG idChild, LONG idThread)
Definition: event.c:98
static VOID FASTCALL IntSetSrvEventMask(UINT EventMin, UINT EventMax)
Definition: event.c:61
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
ULONG Flags
Definition: hook.h:24
#define SRV_EVENT_CREATE
Definition: ntuser.h:1041
Definition: window.c:29
DBG_DEFAULT_CHANNEL(UserEvent)
#define FALSE
Definition: types.h:117
#define SRV_EVENT_NAMECHANGE
Definition: ntuser.h:1037
struct _EVENTPACK EVENTPACK
long LONG
Definition: pedump.c:60
static __inline VOID UserDerefObjectCo(PVOID obj)
Definition: object.h:38
#define SRV_EVENT_MENU
Definition: ntuser.h:1034
THRDESKHEAD head
Definition: ntuser.h:659
#define SRV_EVENT_END_APPLICATION
Definition: ntuser.h:1035
#define APIENTRY
Definition: nt_native.h:48
LRESULT APIENTRY co_IntCallEventProc(HWINEVENTHOOK hook, DWORD event, HWND hWnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime, WINEVENTPROC Proc, INT Mod, ULONG_PTR offPfn)
Definition: callback.c:824
Definition: object.h:3
smooth NULL
Definition: ftsmooth.c:416
ULONGLONG APIENTRY EngGetTickCount(VOID)
Definition: engmisc.c:288
WINEVENTPROC Proc
Definition: hook.h:23
#define WEF_SETBYWNDPTI
Definition: ntuser.h:213
PWND FASTCALL UserGetWindowObject(HWND hWnd)
Definition: window.c:103
UINT eventMin
Definition: hook.h:19
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
PEVENTHOOK pEH
Definition: event.c:14
struct tagEVENTHOOK * PEVENTHOOK
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:243
#define UserHMGetHandle(obj)
Definition: ntuser.h:208
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
_In_ HANDLE Handle
Definition: extypes.h:390
unsigned char BOOLEAN
LONG idThread
Definition: event.c:17
#define ERROR_INVALID_FILTER_PROC
Definition: winerror.h:908
BOOLEAN IntRemoveEvent(PVOID Object)
Definition: event.c:127
#define TRACE(s)
Definition: solgame.cpp:4
unsigned int BOOL
Definition: ntddk_ex.h:94
_Out_ PCLIENT_ID ClientId
Definition: kefuncs.h:1176
LONG NTSTATUS
Definition: precomp.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
#define SRV_EVENT_RUNNING
Definition: ntuser.h:1036
#define QS_EVENT
Definition: undocuser.h:95
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
VOID FASTCALL MsqPostMessage(PTHREADINFO pti, MSG *Msg, BOOLEAN HardwareMessage, DWORD MessageBits, DWORD dwQEvent, LONG_PTR ExtraInfo)
Definition: msgqueue.c:1342
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
static IUnknown Object
Definition: main.c:512
#define POSTEVENT_NWE
Definition: msgqueue.h:125
GLbitfield flags
Definition: glext.h:7161
HANDLE UniqueThread
Definition: compat.h:475
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define WINEVENT_INCONTEXT
Definition: winable.h:35
struct _THREADINFO * pti
Definition: ntuser.h:183
#define KeEnterCriticalRegion()
Definition: ke_x.h:83
Definition: typedefs.h:117
static _In_ DWORD dwflags
Definition: dispmode.c:64
DWORD idThread
Definition: hook.h:22
struct _cl_event * event
Definition: glext.h:7739
uint32_t DWORD_PTR
Definition: typedefs.h:63
LONG idChild
Definition: event.c:16
Status
Definition: gdiplustypes.h:24
static PEVENTTABLE GlobalEvents
Definition: event.c:20
#define ERR(fmt,...)
Definition: debug.h:109
Definition: ntuser.h:657
DWORD dwInstalledEventHooks
Definition: ntuser.h:1024
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:251
DWORD *typedef HANDLE
Definition: winlogon.h:61
#define KeLeaveCriticalRegion()
Definition: ke_x.h:114
FORCEINLINE struct _TEB * NtCurrentTeb(VOID)
Definition: psfuncs.h:420
PVOID UserGetObject(PUSER_HANDLE_TABLE ht, HANDLE handle, HANDLE_TYPE type)
Definition: object.c:462
#define WINEVENT_SKIPOWNTHREAD
Definition: winable.h:33
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
UINT eventMax
Definition: hook.h:20
DWORD state
Definition: ntuser.h:665
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define SRV_EVENT_LOCATIONCHANGE
Definition: ntuser.h:1040
unsigned int UINT
Definition: ndis.h:50
LIST_ENTRY Chain
Definition: hook.h:18
#define ERROR_HOOK_NEEDS_HMOD
Definition: winerror.h:909
#define SRV_EVENT_VALUECHANGE
Definition: ntuser.h:1038
struct _EVENTPACK * PEVENTPACK
HANDLE HMODULE
Definition: typedefs.h:75
#define ULONG_PTR
Definition: config.h:101
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
ULONG_PTR offPfn
Definition: hook.h:25
LONG_PTR LRESULT
Definition: windef.h:209
PUSER_HANDLE_TABLE gHandleTable
Definition: object.c:13
#define WNDS_DESTROYED
Definition: ntuser.h:604
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27
DWORD idProcess
Definition: hook.h:21
#define ERROR_INVALID_HOOK_FILTER
Definition: winerror.h:907
VOID APIENTRY NtUserNotifyWinEvent(DWORD Event, HWND hWnd, LONG idObject, LONG idChild)
Definition: event.c:255