2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/ex/event.c
5 * PURPOSE: Event support
6 * PROGRAMMERS: Alex Ionescu(alex@relsoft.net)
10 /* INCLUDES *****************************************************************/
16 #if defined (ALLOC_PRAGMA)
17 #pragma alloc_text(INIT, ExpInitializeEventImplementation)
20 /* GLOBALS *******************************************************************/
22 POBJECT_TYPE _ExEventObjectType
= NULL
;
24 GENERIC_MAPPING ExpEventMapping
=
26 STANDARD_RIGHTS_READ
| EVENT_QUERY_STATE
,
27 STANDARD_RIGHTS_WRITE
| EVENT_MODIFY_STATE
,
28 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
,
32 static const INFORMATION_CLASS_INFO ExEventInfoClass
[] =
34 /* EventBasicInformation */
35 ICI_SQ_SAME( sizeof(EVENT_BASIC_INFORMATION
), sizeof(ULONG
), ICIF_QUERY
),
38 /* FUNCTIONS *****************************************************************/
43 ExpInitializeEventImplementation(VOID
)
45 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
48 DPRINT("Creating Event Object Type\n");
50 /* Create the Event Object Type */
51 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
52 RtlInitUnicodeString(&Name
, L
"Event");
53 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
54 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(KEVENT
);
55 ObjectTypeInitializer
.GenericMapping
= ExpEventMapping
;
56 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
57 ObjectTypeInitializer
.ValidAccessMask
= EVENT_ALL_ACCESS
;
58 ObjectTypeInitializer
.InvalidAttributes
= OBJ_OPENLINK
;
59 Status
= ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &ExEventObjectType
);
60 if (!NT_SUCCESS(Status
)) return FALSE
;
69 NtClearEvent(IN HANDLE EventHandle
)
75 /* Reference the Object */
76 Status
= ObReferenceObjectByHandle(EventHandle
,
83 /* Check for Success */
84 if(NT_SUCCESS(Status
))
86 /* Clear the Event and Dereference */
88 ObDereferenceObject(Event
);
100 NtCreateEvent(OUT PHANDLE EventHandle
,
101 IN ACCESS_MASK DesiredAccess
,
102 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
103 IN EVENT_TYPE EventType
,
104 IN BOOLEAN InitialState
)
106 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
111 DPRINT("NtCreateEvent(0x%p, 0x%x, 0x%p)\n",
112 EventHandle
, DesiredAccess
, ObjectAttributes
);
114 /* Check if we were called from user-mode */
115 if (PreviousMode
!= KernelMode
)
117 /* Enter SEH Block */
120 /* Check handle pointer */
121 ProbeForWriteHandle(EventHandle
);
123 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
125 /* Return the exception code */
126 _SEH2_YIELD(return _SEH2_GetExceptionCode());
131 /* Create the Object */
132 Status
= ObCreateObject(PreviousMode
,
142 /* Check for Success */
143 if (NT_SUCCESS(Status
))
145 /* Initialize the Event */
146 KeInitializeEvent(Event
,
151 Status
= ObInsertObject((PVOID
)Event
,
158 /* Check for success */
159 if (NT_SUCCESS(Status
))
161 /* Enter SEH for return */
164 /* Return the handle to the caller */
165 *EventHandle
= hEvent
;
167 _SEH2_EXCEPT(ExSystemExceptionFilter())
169 /* Get the exception code */
170 Status
= _SEH2_GetExceptionCode();
185 NtOpenEvent(OUT PHANDLE EventHandle
,
186 IN ACCESS_MASK DesiredAccess
,
187 IN POBJECT_ATTRIBUTES ObjectAttributes
)
190 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
193 DPRINT("NtOpenEvent(0x%p, 0x%x, 0x%p)\n",
194 EventHandle
, DesiredAccess
, ObjectAttributes
);
196 /* Check if we were called from user-mode */
197 if (PreviousMode
!= KernelMode
)
199 /* Enter SEH Block */
202 /* Check handle pointer */
203 ProbeForWriteHandle(EventHandle
);
205 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
207 /* Return the exception code */
208 _SEH2_YIELD(return _SEH2_GetExceptionCode());
213 /* Open the Object */
214 Status
= ObOpenObjectByName(ObjectAttributes
,
222 /* Check for success */
223 if (NT_SUCCESS(Status
))
225 /* Enter SEH for return */
228 /* Return the handle to the caller */
229 *EventHandle
= hEvent
;
231 _SEH2_EXCEPT(ExSystemExceptionFilter())
233 /* Get the exception code */
234 Status
= _SEH2_GetExceptionCode();
248 NtPulseEvent(IN HANDLE EventHandle
,
249 OUT PLONG PreviousState OPTIONAL
)
252 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
255 DPRINT("NtPulseEvent(EventHandle 0%p PreviousState 0%p)\n",
256 EventHandle
, PreviousState
);
258 /* Check if we were called from user-mode */
259 if((PreviousState
) && (PreviousMode
!= KernelMode
))
261 /* Entry SEH Block */
264 /* Make sure the state pointer is valid */
265 ProbeForWriteLong(PreviousState
);
267 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
269 /* Return the exception code */
270 _SEH2_YIELD(return _SEH2_GetExceptionCode());
275 /* Open the Object */
276 Status
= ObReferenceObjectByHandle(EventHandle
,
283 /* Check for success */
284 if(NT_SUCCESS(Status
))
286 /* Pulse the Event */
287 LONG Prev
= KePulseEvent(Event
, EVENT_INCREMENT
, FALSE
);
288 ObDereferenceObject(Event
);
290 /* Check if caller wants the old state back */
293 /* Entry SEH Block for return */
296 /* Return previous state */
297 *PreviousState
= Prev
;
299 _SEH2_EXCEPT(ExSystemExceptionFilter())
301 /* Get the exception code */
302 Status
= _SEH2_GetExceptionCode();
317 NtQueryEvent(IN HANDLE EventHandle
,
318 IN EVENT_INFORMATION_CLASS EventInformationClass
,
319 OUT PVOID EventInformation
,
320 IN ULONG EventInformationLength
,
321 OUT PULONG ReturnLength OPTIONAL
)
324 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
326 PEVENT_BASIC_INFORMATION BasicInfo
=
327 (PEVENT_BASIC_INFORMATION
)EventInformation
;
329 DPRINT("NtQueryEvent(0x%p, 0x%x)\n", EventHandle
, EventInformationClass
);
331 /* Check buffers and class validity */
332 Status
= DefaultQueryInfoBufferCheck(EventInformationClass
,
334 sizeof(ExEventInfoClass
) /
335 sizeof(ExEventInfoClass
[0]),
337 EventInformationLength
,
341 if(!NT_SUCCESS(Status
))
343 /* Invalid buffers */
344 DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status
);
349 Status
= ObReferenceObjectByHandle(EventHandle
,
356 /* Check for success */
357 if(NT_SUCCESS(Status
))
359 /* Entry SEH Block */
362 /* Return Event Type and State */
363 BasicInfo
->EventType
= Event
->Header
.Type
;
364 BasicInfo
->EventState
= KeReadStateEvent(Event
);
367 if(ReturnLength
) *ReturnLength
= sizeof(EVENT_BASIC_INFORMATION
);
369 _SEH2_EXCEPT(ExSystemExceptionFilter())
371 /* Get the exception code */
372 Status
= _SEH2_GetExceptionCode();
376 /* Dereference the Object */
377 ObDereferenceObject(Event
);
389 NtResetEvent(IN HANDLE EventHandle
,
390 OUT PLONG PreviousState OPTIONAL
)
393 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
396 DPRINT("NtResetEvent(EventHandle 0%p PreviousState 0%p)\n",
397 EventHandle
, PreviousState
);
399 /* Check if we were called from user-mode */
400 if ((PreviousState
) && (PreviousMode
!= KernelMode
))
402 /* Entry SEH Block */
405 /* Make sure the state pointer is valid */
406 ProbeForWriteLong(PreviousState
);
408 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
410 /* Return the exception code */
411 _SEH2_YIELD(return _SEH2_GetExceptionCode());
416 /* Open the Object */
417 Status
= ObReferenceObjectByHandle(EventHandle
,
424 /* Check for success */
425 if(NT_SUCCESS(Status
))
427 /* Reset the Event */
428 LONG Prev
= KeResetEvent(Event
);
429 ObDereferenceObject(Event
);
431 /* Check if caller wants the old state back */
434 /* Entry SEH Block for return */
437 /* Return previous state */
438 *PreviousState
= Prev
;
440 _SEH2_EXCEPT(ExSystemExceptionFilter())
442 /* Get the exception code */
443 Status
= _SEH2_GetExceptionCode();
458 NtSetEvent(IN HANDLE EventHandle
,
459 OUT PLONG PreviousState OPTIONAL
)
462 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
465 DPRINT("NtSetEvent(EventHandle 0%p PreviousState 0%p)\n",
466 EventHandle
, PreviousState
);
468 /* Check if we were called from user-mode */
469 if ((PreviousState
) && (PreviousMode
!= KernelMode
))
471 /* Entry SEH Block */
474 /* Make sure the state pointer is valid */
475 ProbeForWriteLong(PreviousState
);
477 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
479 /* Return the exception code */
480 _SEH2_YIELD(return _SEH2_GetExceptionCode());
485 /* Open the Object */
486 Status
= ObReferenceObjectByHandle(EventHandle
,
492 if (NT_SUCCESS(Status
))
495 LONG Prev
= KeSetEvent(Event
, EVENT_INCREMENT
, FALSE
);
496 ObDereferenceObject(Event
);
498 /* Check if caller wants the old state back */
501 /* Entry SEH Block for return */
504 /* Return previous state */
505 *PreviousState
= Prev
;
507 _SEH2_EXCEPT(ExSystemExceptionFilter())
509 Status
= _SEH2_GetExceptionCode();
524 NtSetEventBoostPriority(IN HANDLE EventHandle
)
530 /* Open the Object */
531 Status
= ObReferenceObjectByHandle(EventHandle
,
537 if (NT_SUCCESS(Status
))
540 KeSetEventBoostPriority(Event
, NULL
);
541 ObDereferenceObject(Event
);