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
| SYNCHRONIZE
| EVENT_QUERY_STATE
,
27 STANDARD_RIGHTS_WRITE
| SYNCHRONIZE
| EVENT_MODIFY_STATE
,
28 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
| EVENT_QUERY_STATE
,
31 static const INFORMATION_CLASS_INFO ExEventInfoClass
[] =
33 /* EventBasicInformation */
34 ICI_SQ_SAME( sizeof(EVENT_BASIC_INFORMATION
), sizeof(ULONG
), ICIF_QUERY
),
37 /* FUNCTIONS *****************************************************************/
42 ExpInitializeEventImplementation(VOID
)
44 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
46 DPRINT("Creating Event Object Type\n");
48 /* Create the Event Object Type */
49 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
50 RtlInitUnicodeString(&Name
, L
"Event");
51 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
52 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(KEVENT
);
53 ObjectTypeInitializer
.GenericMapping
= ExpEventMapping
;
54 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
55 ObjectTypeInitializer
.ValidAccessMask
= EVENT_ALL_ACCESS
;
56 ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &ExEventObjectType
);
64 NtClearEvent(IN HANDLE EventHandle
)
70 /* Reference the Object */
71 Status
= ObReferenceObjectByHandle(EventHandle
,
78 /* Check for Success */
79 if(NT_SUCCESS(Status
))
81 /* Clear the Event and Dereference */
83 ObDereferenceObject(Event
);
95 NtCreateEvent(OUT PHANDLE EventHandle
,
96 IN ACCESS_MASK DesiredAccess
,
97 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
98 IN EVENT_TYPE EventType
,
99 IN BOOLEAN InitialState
)
101 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
106 DPRINT("NtCreateEvent(0x%p, 0x%x, 0x%p)\n",
107 EventHandle
, DesiredAccess
, ObjectAttributes
);
109 /* Check if we were called from user-mode */
110 if (PreviousMode
!= KernelMode
)
112 /* Enter SEH Block */
115 /* Check handle pointer */
116 ProbeForWriteHandle(EventHandle
);
118 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
120 /* Return the exception code */
121 _SEH2_YIELD(return _SEH2_GetExceptionCode());
126 /* Create the Object */
127 Status
= ObCreateObject(PreviousMode
,
137 /* Check for Success */
138 if(NT_SUCCESS(Status
))
140 /* Initalize the Event */
141 KeInitializeEvent(Event
,
146 Status
= ObInsertObject((PVOID
)Event
,
153 /* Check for success */
154 if(NT_SUCCESS(Status
))
156 /* Enter SEH for return */
159 /* Return the handle to the caller */
160 *EventHandle
= hEvent
;
162 _SEH2_EXCEPT(ExSystemExceptionFilter())
164 /* Get the exception code */
165 Status
= _SEH2_GetExceptionCode();
180 NtOpenEvent(OUT PHANDLE EventHandle
,
181 IN ACCESS_MASK DesiredAccess
,
182 IN POBJECT_ATTRIBUTES ObjectAttributes
)
185 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
188 DPRINT("NtOpenEvent(0x%p, 0x%x, 0x%p)\n",
189 EventHandle
, DesiredAccess
, ObjectAttributes
);
191 /* Check if we were called from user-mode */
192 if (PreviousMode
!= KernelMode
)
194 /* Enter SEH Block */
197 /* Check handle pointer */
198 ProbeForWriteHandle(EventHandle
);
200 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
202 /* Return the exception code */
203 _SEH2_YIELD(return _SEH2_GetExceptionCode());
208 /* Open the Object */
209 Status
= ObOpenObjectByName(ObjectAttributes
,
217 /* Check for success */
218 if (NT_SUCCESS(Status
))
220 /* Enter SEH for return */
223 /* Return the handle to the caller */
224 *EventHandle
= hEvent
;
226 _SEH2_EXCEPT(ExSystemExceptionFilter())
228 /* Get the exception code */
229 Status
= _SEH2_GetExceptionCode();
243 NtPulseEvent(IN HANDLE EventHandle
,
244 OUT PLONG PreviousState OPTIONAL
)
247 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
250 DPRINT("NtPulseEvent(EventHandle 0%x PreviousState 0%x)\n",
251 EventHandle
, PreviousState
);
253 /* Check if we were called from user-mode */
254 if((PreviousState
) && (PreviousMode
!= KernelMode
))
256 /* Entry SEH Block */
259 /* Make sure the state pointer is valid */
260 ProbeForWriteLong(PreviousState
);
262 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
264 /* Return the exception code */
265 _SEH2_YIELD(return _SEH2_GetExceptionCode());
270 /* Open the Object */
271 Status
= ObReferenceObjectByHandle(EventHandle
,
278 /* Check for success */
279 if(NT_SUCCESS(Status
))
281 /* Pulse the Event */
282 LONG Prev
= KePulseEvent(Event
, EVENT_INCREMENT
, FALSE
);
283 ObDereferenceObject(Event
);
285 /* Check if caller wants the old state back */
288 /* Entry SEH Block for return */
291 /* Return previous state */
292 *PreviousState
= Prev
;
294 _SEH2_EXCEPT(ExSystemExceptionFilter())
296 /* Get the exception code */
297 Status
= _SEH2_GetExceptionCode();
312 NtQueryEvent(IN HANDLE EventHandle
,
313 IN EVENT_INFORMATION_CLASS EventInformationClass
,
314 OUT PVOID EventInformation
,
315 IN ULONG EventInformationLength
,
316 OUT PULONG ReturnLength OPTIONAL
)
319 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
321 PEVENT_BASIC_INFORMATION BasicInfo
=
322 (PEVENT_BASIC_INFORMATION
)EventInformation
;
324 DPRINT("NtQueryEvent(0x%p, 0x%x)\n", EventHandle
, EventInformationClass
);
326 /* Check buffers and class validity */
327 Status
= DefaultQueryInfoBufferCheck(EventInformationClass
,
329 sizeof(ExEventInfoClass
) /
330 sizeof(ExEventInfoClass
[0]),
332 EventInformationLength
,
336 if(!NT_SUCCESS(Status
))
338 /* Invalid buffers */
339 DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status
);
344 Status
= ObReferenceObjectByHandle(EventHandle
,
351 /* Check for success */
352 if(NT_SUCCESS(Status
))
354 /* Entry SEH Block */
357 /* Return Event Type and State */
358 BasicInfo
->EventType
= Event
->Header
.Type
;
359 BasicInfo
->EventState
= KeReadStateEvent(Event
);
362 if(ReturnLength
) *ReturnLength
= sizeof(EVENT_BASIC_INFORMATION
);
364 _SEH2_EXCEPT(ExSystemExceptionFilter())
366 /* Get the exception code */
367 Status
= _SEH2_GetExceptionCode();
371 /* Dereference the Object */
372 ObDereferenceObject(Event
);
384 NtResetEvent(IN HANDLE EventHandle
,
385 OUT PLONG PreviousState OPTIONAL
)
388 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
391 DPRINT("NtResetEvent(EventHandle 0%x PreviousState 0%x)\n",
392 EventHandle
, PreviousState
);
394 /* Check if we were called from user-mode */
395 if ((PreviousState
) && (PreviousMode
!= KernelMode
))
397 /* Entry SEH Block */
400 /* Make sure the state pointer is valid */
401 ProbeForWriteLong(PreviousState
);
403 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
405 /* Return the exception code */
406 _SEH2_YIELD(return _SEH2_GetExceptionCode());
411 /* Open the Object */
412 Status
= ObReferenceObjectByHandle(EventHandle
,
419 /* Check for success */
420 if(NT_SUCCESS(Status
))
422 /* Reset the Event */
423 LONG Prev
= KeResetEvent(Event
);
424 ObDereferenceObject(Event
);
426 /* Check if caller wants the old state back */
429 /* Entry SEH Block for return */
432 /* Return previous state */
433 *PreviousState
= Prev
;
435 _SEH2_EXCEPT(ExSystemExceptionFilter())
437 /* Get the exception code */
438 Status
= _SEH2_GetExceptionCode();
453 NtSetEvent(IN HANDLE EventHandle
,
454 OUT PLONG PreviousState OPTIONAL
)
457 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
460 DPRINT("NtSetEvent(EventHandle 0%x PreviousState 0%x)\n",
461 EventHandle
, PreviousState
);
463 /* Check if we were called from user-mode */
464 if ((PreviousState
) && (PreviousMode
!= KernelMode
))
466 /* Entry SEH Block */
469 /* Make sure the state pointer is valid */
470 ProbeForWriteLong(PreviousState
);
472 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
474 /* Return the exception code */
475 _SEH2_YIELD(return _SEH2_GetExceptionCode());
480 /* Open the Object */
481 Status
= ObReferenceObjectByHandle(EventHandle
,
487 if (NT_SUCCESS(Status
))
490 LONG Prev
= KeSetEvent(Event
, EVENT_INCREMENT
, FALSE
);
491 ObDereferenceObject(Event
);
493 /* Check if caller wants the old state back */
496 /* Entry SEH Block for return */
499 /* Return previous state */
500 *PreviousState
= Prev
;
502 _SEH2_EXCEPT(ExSystemExceptionFilter())
504 Status
= _SEH2_GetExceptionCode();
519 NtSetEventBoostPriority(IN HANDLE EventHandle
)
525 /* Open the Object */
526 Status
= ObReferenceObjectByHandle(EventHandle
,
532 if (NT_SUCCESS(Status
))
535 KeSetEventBoostPriority(Event
, NULL
);
536 ObDereferenceObject(Event
);