[CLT2012]
[reactos.git] / ntoskrnl / ex / event.c
1 /*
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)
7 * Thomas Weidenmueller
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 #if defined (ALLOC_PRAGMA)
17 #pragma alloc_text(INIT, ExpInitializeEventImplementation)
18 #endif
19
20 /* GLOBALS *******************************************************************/
21
22 POBJECT_TYPE _ExEventObjectType = NULL;
23
24 GENERIC_MAPPING ExpEventMapping =
25 {
26 STANDARD_RIGHTS_READ | SYNCHRONIZE | EVENT_QUERY_STATE,
27 STANDARD_RIGHTS_WRITE | SYNCHRONIZE | EVENT_MODIFY_STATE,
28 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | EVENT_QUERY_STATE,
29 EVENT_ALL_ACCESS};
30
31 static const INFORMATION_CLASS_INFO ExEventInfoClass[] =
32 {
33 /* EventBasicInformation */
34 ICI_SQ_SAME( sizeof(EVENT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY),
35 };
36
37 /* FUNCTIONS *****************************************************************/
38
39 VOID
40 INIT_FUNCTION
41 NTAPI
42 ExpInitializeEventImplementation(VOID)
43 {
44 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
45 UNICODE_STRING Name;
46 DPRINT("Creating Event Object Type\n");
47
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);
57 }
58
59 /*
60 * @implemented
61 */
62 NTSTATUS
63 NTAPI
64 NtClearEvent(IN HANDLE EventHandle)
65 {
66 PKEVENT Event;
67 NTSTATUS Status;
68 PAGED_CODE();
69
70 /* Reference the Object */
71 Status = ObReferenceObjectByHandle(EventHandle,
72 EVENT_MODIFY_STATE,
73 ExEventObjectType,
74 ExGetPreviousMode(),
75 (PVOID*)&Event,
76 NULL);
77
78 /* Check for Success */
79 if(NT_SUCCESS(Status))
80 {
81 /* Clear the Event and Dereference */
82 KeClearEvent(Event);
83 ObDereferenceObject(Event);
84 }
85
86 /* Return Status */
87 return Status;
88 }
89
90 /*
91 * @implemented
92 */
93 NTSTATUS
94 NTAPI
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)
100 {
101 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
102 PKEVENT Event;
103 HANDLE hEvent;
104 NTSTATUS Status;
105 PAGED_CODE();
106 DPRINT("NtCreateEvent(0x%p, 0x%x, 0x%p)\n",
107 EventHandle, DesiredAccess, ObjectAttributes);
108
109 /* Check if we were called from user-mode */
110 if (PreviousMode != KernelMode)
111 {
112 /* Enter SEH Block */
113 _SEH2_TRY
114 {
115 /* Check handle pointer */
116 ProbeForWriteHandle(EventHandle);
117 }
118 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
119 {
120 /* Return the exception code */
121 _SEH2_YIELD(return _SEH2_GetExceptionCode());
122 }
123 _SEH2_END;
124 }
125
126 /* Create the Object */
127 Status = ObCreateObject(PreviousMode,
128 ExEventObjectType,
129 ObjectAttributes,
130 PreviousMode,
131 NULL,
132 sizeof(KEVENT),
133 0,
134 0,
135 (PVOID*)&Event);
136
137 /* Check for Success */
138 if(NT_SUCCESS(Status))
139 {
140 /* Initalize the Event */
141 KeInitializeEvent(Event,
142 EventType,
143 InitialState);
144
145 /* Insert it */
146 Status = ObInsertObject((PVOID)Event,
147 NULL,
148 DesiredAccess,
149 0,
150 NULL,
151 &hEvent);
152
153 /* Check for success */
154 if(NT_SUCCESS(Status))
155 {
156 /* Enter SEH for return */
157 _SEH2_TRY
158 {
159 /* Return the handle to the caller */
160 *EventHandle = hEvent;
161 }
162 _SEH2_EXCEPT(ExSystemExceptionFilter())
163 {
164 /* Get the exception code */
165 Status = _SEH2_GetExceptionCode();
166 }
167 _SEH2_END;
168 }
169 }
170
171 /* Return Status */
172 return Status;
173 }
174
175 /*
176 * @implemented
177 */
178 NTSTATUS
179 NTAPI
180 NtOpenEvent(OUT PHANDLE EventHandle,
181 IN ACCESS_MASK DesiredAccess,
182 IN POBJECT_ATTRIBUTES ObjectAttributes)
183 {
184 HANDLE hEvent;
185 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
186 NTSTATUS Status;
187 PAGED_CODE();
188 DPRINT("NtOpenEvent(0x%p, 0x%x, 0x%p)\n",
189 EventHandle, DesiredAccess, ObjectAttributes);
190
191 /* Check if we were called from user-mode */
192 if (PreviousMode != KernelMode)
193 {
194 /* Enter SEH Block */
195 _SEH2_TRY
196 {
197 /* Check handle pointer */
198 ProbeForWriteHandle(EventHandle);
199 }
200 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
201 {
202 /* Return the exception code */
203 _SEH2_YIELD(return _SEH2_GetExceptionCode());
204 }
205 _SEH2_END;
206 }
207
208 /* Open the Object */
209 Status = ObOpenObjectByName(ObjectAttributes,
210 ExEventObjectType,
211 PreviousMode,
212 NULL,
213 DesiredAccess,
214 NULL,
215 &hEvent);
216
217 /* Check for success */
218 if (NT_SUCCESS(Status))
219 {
220 /* Enter SEH for return */
221 _SEH2_TRY
222 {
223 /* Return the handle to the caller */
224 *EventHandle = hEvent;
225 }
226 _SEH2_EXCEPT(ExSystemExceptionFilter())
227 {
228 /* Get the exception code */
229 Status = _SEH2_GetExceptionCode();
230 }
231 _SEH2_END;
232 }
233
234 /* Return status */
235 return Status;
236 }
237
238 /*
239 * @implemented
240 */
241 NTSTATUS
242 NTAPI
243 NtPulseEvent(IN HANDLE EventHandle,
244 OUT PLONG PreviousState OPTIONAL)
245 {
246 PKEVENT Event;
247 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
248 NTSTATUS Status;
249 PAGED_CODE();
250 DPRINT("NtPulseEvent(EventHandle 0%x PreviousState 0%x)\n",
251 EventHandle, PreviousState);
252
253 /* Check if we were called from user-mode */
254 if((PreviousState) && (PreviousMode != KernelMode))
255 {
256 /* Entry SEH Block */
257 _SEH2_TRY
258 {
259 /* Make sure the state pointer is valid */
260 ProbeForWriteLong(PreviousState);
261 }
262 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
263 {
264 /* Return the exception code */
265 _SEH2_YIELD(return _SEH2_GetExceptionCode());
266 }
267 _SEH2_END;
268 }
269
270 /* Open the Object */
271 Status = ObReferenceObjectByHandle(EventHandle,
272 EVENT_MODIFY_STATE,
273 ExEventObjectType,
274 PreviousMode,
275 (PVOID*)&Event,
276 NULL);
277
278 /* Check for success */
279 if(NT_SUCCESS(Status))
280 {
281 /* Pulse the Event */
282 LONG Prev = KePulseEvent(Event, EVENT_INCREMENT, FALSE);
283 ObDereferenceObject(Event);
284
285 /* Check if caller wants the old state back */
286 if(PreviousState)
287 {
288 /* Entry SEH Block for return */
289 _SEH2_TRY
290 {
291 /* Return previous state */
292 *PreviousState = Prev;
293 }
294 _SEH2_EXCEPT(ExSystemExceptionFilter())
295 {
296 /* Get the exception code */
297 Status = _SEH2_GetExceptionCode();
298 }
299 _SEH2_END;
300 }
301 }
302
303 /* Return Status */
304 return Status;
305 }
306
307 /*
308 * @implemented
309 */
310 NTSTATUS
311 NTAPI
312 NtQueryEvent(IN HANDLE EventHandle,
313 IN EVENT_INFORMATION_CLASS EventInformationClass,
314 OUT PVOID EventInformation,
315 IN ULONG EventInformationLength,
316 OUT PULONG ReturnLength OPTIONAL)
317 {
318 PKEVENT Event;
319 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
320 NTSTATUS Status;
321 PEVENT_BASIC_INFORMATION BasicInfo =
322 (PEVENT_BASIC_INFORMATION)EventInformation;
323 PAGED_CODE();
324 DPRINT("NtQueryEvent(0x%p, 0x%x)\n", EventHandle, EventInformationClass);
325
326 /* Check buffers and class validity */
327 Status = DefaultQueryInfoBufferCheck(EventInformationClass,
328 ExEventInfoClass,
329 sizeof(ExEventInfoClass) /
330 sizeof(ExEventInfoClass[0]),
331 EventInformation,
332 EventInformationLength,
333 ReturnLength,
334 NULL,
335 PreviousMode);
336 if(!NT_SUCCESS(Status))
337 {
338 /* Invalid buffers */
339 DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
340 return Status;
341 }
342
343 /* Get the Object */
344 Status = ObReferenceObjectByHandle(EventHandle,
345 EVENT_QUERY_STATE,
346 ExEventObjectType,
347 PreviousMode,
348 (PVOID*)&Event,
349 NULL);
350
351 /* Check for success */
352 if(NT_SUCCESS(Status))
353 {
354 /* Entry SEH Block */
355 _SEH2_TRY
356 {
357 /* Return Event Type and State */
358 BasicInfo->EventType = Event->Header.Type;
359 BasicInfo->EventState = KeReadStateEvent(Event);
360
361 /* Return length */
362 if(ReturnLength) *ReturnLength = sizeof(EVENT_BASIC_INFORMATION);
363 }
364 _SEH2_EXCEPT(ExSystemExceptionFilter())
365 {
366 /* Get the exception code */
367 Status = _SEH2_GetExceptionCode();
368 }
369 _SEH2_END;
370
371 /* Dereference the Object */
372 ObDereferenceObject(Event);
373 }
374
375 /* Return status */
376 return Status;
377 }
378
379 /*
380 * @implemented
381 */
382 NTSTATUS
383 NTAPI
384 NtResetEvent(IN HANDLE EventHandle,
385 OUT PLONG PreviousState OPTIONAL)
386 {
387 PKEVENT Event;
388 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
389 NTSTATUS Status;
390 PAGED_CODE();
391 DPRINT("NtResetEvent(EventHandle 0%x PreviousState 0%x)\n",
392 EventHandle, PreviousState);
393
394 /* Check if we were called from user-mode */
395 if ((PreviousState) && (PreviousMode != KernelMode))
396 {
397 /* Entry SEH Block */
398 _SEH2_TRY
399 {
400 /* Make sure the state pointer is valid */
401 ProbeForWriteLong(PreviousState);
402 }
403 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
404 {
405 /* Return the exception code */
406 _SEH2_YIELD(return _SEH2_GetExceptionCode());
407 }
408 _SEH2_END;
409 }
410
411 /* Open the Object */
412 Status = ObReferenceObjectByHandle(EventHandle,
413 EVENT_MODIFY_STATE,
414 ExEventObjectType,
415 PreviousMode,
416 (PVOID*)&Event,
417 NULL);
418
419 /* Check for success */
420 if(NT_SUCCESS(Status))
421 {
422 /* Reset the Event */
423 LONG Prev = KeResetEvent(Event);
424 ObDereferenceObject(Event);
425
426 /* Check if caller wants the old state back */
427 if(PreviousState)
428 {
429 /* Entry SEH Block for return */
430 _SEH2_TRY
431 {
432 /* Return previous state */
433 *PreviousState = Prev;
434 }
435 _SEH2_EXCEPT(ExSystemExceptionFilter())
436 {
437 /* Get the exception code */
438 Status = _SEH2_GetExceptionCode();
439 }
440 _SEH2_END;
441 }
442 }
443
444 /* Return Status */
445 return Status;
446 }
447
448 /*
449 * @implemented
450 */
451 NTSTATUS
452 NTAPI
453 NtSetEvent(IN HANDLE EventHandle,
454 OUT PLONG PreviousState OPTIONAL)
455 {
456 PKEVENT Event;
457 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
458 NTSTATUS Status;
459 PAGED_CODE();
460 DPRINT("NtSetEvent(EventHandle 0%x PreviousState 0%x)\n",
461 EventHandle, PreviousState);
462
463 /* Check if we were called from user-mode */
464 if ((PreviousState) && (PreviousMode != KernelMode))
465 {
466 /* Entry SEH Block */
467 _SEH2_TRY
468 {
469 /* Make sure the state pointer is valid */
470 ProbeForWriteLong(PreviousState);
471 }
472 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
473 {
474 /* Return the exception code */
475 _SEH2_YIELD(return _SEH2_GetExceptionCode());
476 }
477 _SEH2_END;
478 }
479
480 /* Open the Object */
481 Status = ObReferenceObjectByHandle(EventHandle,
482 EVENT_MODIFY_STATE,
483 ExEventObjectType,
484 PreviousMode,
485 (PVOID*)&Event,
486 NULL);
487 if (NT_SUCCESS(Status))
488 {
489 /* Set the Event */
490 LONG Prev = KeSetEvent(Event, EVENT_INCREMENT, FALSE);
491 ObDereferenceObject(Event);
492
493 /* Check if caller wants the old state back */
494 if (PreviousState)
495 {
496 /* Entry SEH Block for return */
497 _SEH2_TRY
498 {
499 /* Return previous state */
500 *PreviousState = Prev;
501 }
502 _SEH2_EXCEPT(ExSystemExceptionFilter())
503 {
504 Status = _SEH2_GetExceptionCode();
505 }
506 _SEH2_END;
507 }
508 }
509
510 /* Return Status */
511 return Status;
512 }
513
514 /*
515 * @implemented
516 */
517 NTSTATUS
518 NTAPI
519 NtSetEventBoostPriority(IN HANDLE EventHandle)
520 {
521 PKEVENT Event;
522 NTSTATUS Status;
523 PAGED_CODE();
524
525 /* Open the Object */
526 Status = ObReferenceObjectByHandle(EventHandle,
527 EVENT_MODIFY_STATE,
528 ExEventObjectType,
529 ExGetPreviousMode(),
530 (PVOID*)&Event,
531 NULL);
532 if (NT_SUCCESS(Status))
533 {
534 /* Set the Event */
535 KeSetEventBoostPriority(Event, NULL);
536 ObDereferenceObject(Event);
537 }
538
539 /* Return Status */
540 return Status;
541 }
542
543 /* EOF */