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