4db20f50ba5a838801b6458d32c411f47d14f51e
[reactos.git] / reactos / ntoskrnl / ex / event.c
1 /* $Id:$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/nt/event.c
6 * PURPOSE: Named event support
7 *
8 * PROGRAMMERS: Philip Susi and David Welch
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* GLOBALS *******************************************************************/
18
19 POBJECT_TYPE EXPORTED ExEventObjectType = NULL;
20
21 static GENERIC_MAPPING ExpEventMapping = {
22 STANDARD_RIGHTS_READ | SYNCHRONIZE | EVENT_QUERY_STATE,
23 STANDARD_RIGHTS_WRITE | SYNCHRONIZE | EVENT_MODIFY_STATE,
24 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | EVENT_QUERY_STATE,
25 EVENT_ALL_ACCESS};
26
27 static const INFORMATION_CLASS_INFO ExEventInfoClass[] =
28 {
29 ICI_SQ_SAME( sizeof(EVENT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* EventBasicInformation */
30 };
31
32 /* FUNCTIONS *****************************************************************/
33
34 NTSTATUS STDCALL
35 NtpCreateEvent(PVOID ObjectBody,
36 PVOID Parent,
37 PWSTR RemainingPath,
38 POBJECT_ATTRIBUTES ObjectAttributes)
39 {
40 DPRINT("NtpCreateEvent(ObjectBody %x, Parent %x, RemainingPath %S)\n",
41 ObjectBody, Parent, RemainingPath);
42
43 if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
44 {
45 return(STATUS_UNSUCCESSFUL);
46 }
47
48 return(STATUS_SUCCESS);
49 }
50
51
52 VOID INIT_FUNCTION
53 ExpInitializeEventImplementation(VOID)
54 {
55 ExEventObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
56
57 RtlpCreateUnicodeString(&ExEventObjectType->TypeName, L"Event", NonPagedPool);
58
59 ExEventObjectType->Tag = TAG('E', 'V', 'T', 'T');
60 ExEventObjectType->PeakObjects = 0;
61 ExEventObjectType->PeakHandles = 0;
62 ExEventObjectType->TotalObjects = 0;
63 ExEventObjectType->TotalHandles = 0;
64 ExEventObjectType->PagedPoolCharge = 0;
65 ExEventObjectType->NonpagedPoolCharge = sizeof(KEVENT);
66 ExEventObjectType->Mapping = &ExpEventMapping;
67 ExEventObjectType->Dump = NULL;
68 ExEventObjectType->Open = NULL;
69 ExEventObjectType->Close = NULL;
70 ExEventObjectType->Delete = NULL;
71 ExEventObjectType->Parse = NULL;
72 ExEventObjectType->Security = NULL;
73 ExEventObjectType->QueryName = NULL;
74 ExEventObjectType->OkayToClose = NULL;
75 ExEventObjectType->Create = NtpCreateEvent;
76 ExEventObjectType->DuplicationNotify = NULL;
77
78 ObpCreateTypeObject(ExEventObjectType);
79 }
80
81
82 /*
83 * @implemented
84 */
85 NTSTATUS STDCALL
86 NtClearEvent(IN HANDLE EventHandle)
87 {
88 PKEVENT Event;
89 NTSTATUS Status;
90
91 PAGED_CODE();
92
93 Status = ObReferenceObjectByHandle(EventHandle,
94 EVENT_MODIFY_STATE,
95 ExEventObjectType,
96 ExGetPreviousMode(),
97 (PVOID*)&Event,
98 NULL);
99 if(NT_SUCCESS(Status))
100 {
101 KeClearEvent(Event);
102 ObDereferenceObject(Event);
103 }
104
105 return Status;
106 }
107
108
109 /*
110 * @implemented
111 */
112 NTSTATUS STDCALL
113 NtCreateEvent(OUT PHANDLE EventHandle,
114 IN ACCESS_MASK DesiredAccess,
115 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
116 IN EVENT_TYPE EventType,
117 IN BOOLEAN InitialState)
118 {
119 KPROCESSOR_MODE PreviousMode;
120 PKEVENT Event;
121 HANDLE hEvent;
122 NTSTATUS Status = STATUS_SUCCESS;
123
124 PAGED_CODE();
125
126 PreviousMode = ExGetPreviousMode();
127
128 if(PreviousMode == UserMode)
129 {
130 _SEH_TRY
131 {
132 ProbeForWrite(EventHandle,
133 sizeof(HANDLE),
134 sizeof(ULONG));
135 }
136 _SEH_HANDLE
137 {
138 Status = _SEH_GetExceptionCode();
139 }
140 _SEH_END;
141
142 if(!NT_SUCCESS(Status))
143 {
144 return Status;
145 }
146 }
147
148 Status = ObCreateObject(PreviousMode,
149 ExEventObjectType,
150 ObjectAttributes,
151 PreviousMode,
152 NULL,
153 sizeof(KEVENT),
154 0,
155 0,
156 (PVOID*)&Event);
157 if(NT_SUCCESS(Status))
158 {
159 KeInitializeEvent(Event,
160 EventType,
161 InitialState);
162
163
164 Status = ObInsertObject((PVOID)Event,
165 NULL,
166 DesiredAccess,
167 0,
168 NULL,
169 &hEvent);
170 ObDereferenceObject(Event);
171
172 if(NT_SUCCESS(Status))
173 {
174 _SEH_TRY
175 {
176 *EventHandle = hEvent;
177 }
178 _SEH_HANDLE
179 {
180 Status = _SEH_GetExceptionCode();
181 }
182 _SEH_END;
183 }
184 }
185
186 return Status;
187 }
188
189
190 /*
191 * @implemented
192 */
193 NTSTATUS STDCALL
194 NtOpenEvent(OUT PHANDLE EventHandle,
195 IN ACCESS_MASK DesiredAccess,
196 IN POBJECT_ATTRIBUTES ObjectAttributes)
197 {
198 HANDLE hEvent;
199 KPROCESSOR_MODE PreviousMode;
200 NTSTATUS Status = STATUS_SUCCESS;
201
202 PAGED_CODE();
203
204 DPRINT("NtOpenEvent(0x%x, 0x%x, 0x%x)\n", EventHandle, DesiredAccess, ObjectAttributes);
205
206 PreviousMode = ExGetPreviousMode();
207
208 if(PreviousMode == UserMode)
209 {
210 _SEH_TRY
211 {
212 ProbeForWrite(EventHandle,
213 sizeof(HANDLE),
214 sizeof(ULONG));
215 }
216 _SEH_HANDLE
217 {
218 Status = _SEH_GetExceptionCode();
219 }
220 _SEH_END;
221
222 if(!NT_SUCCESS(Status))
223 {
224 return Status;
225 }
226 }
227
228 Status = ObOpenObjectByName(ObjectAttributes,
229 ExEventObjectType,
230 NULL,
231 PreviousMode,
232 DesiredAccess,
233 NULL,
234 &hEvent);
235
236 if(NT_SUCCESS(Status))
237 {
238 _SEH_TRY
239 {
240 *EventHandle = hEvent;
241 }
242 _SEH_HANDLE
243 {
244 Status = _SEH_GetExceptionCode();
245 }
246 _SEH_END;
247 }
248
249 return Status;
250 }
251
252
253 /*
254 * @implemented
255 */
256 NTSTATUS STDCALL
257 NtPulseEvent(IN HANDLE EventHandle,
258 OUT PLONG PreviousState OPTIONAL)
259 {
260 PKEVENT Event;
261 KPROCESSOR_MODE PreviousMode;
262 NTSTATUS Status = STATUS_SUCCESS;
263
264 PAGED_CODE();
265
266 DPRINT("NtPulseEvent(EventHandle 0%x PreviousState 0%x)\n",
267 EventHandle, PreviousState);
268
269 PreviousMode = ExGetPreviousMode();
270
271 if(PreviousState != NULL && PreviousMode == UserMode)
272 {
273 _SEH_TRY
274 {
275 ProbeForWrite(PreviousState,
276 sizeof(LONG),
277 sizeof(ULONG));
278 }
279 _SEH_HANDLE
280 {
281 Status = _SEH_GetExceptionCode();
282 }
283 _SEH_END;
284
285 if(!NT_SUCCESS(Status))
286 {
287 return Status;
288 }
289 }
290
291 Status = ObReferenceObjectByHandle(EventHandle,
292 EVENT_MODIFY_STATE,
293 ExEventObjectType,
294 PreviousMode,
295 (PVOID*)&Event,
296 NULL);
297 if(NT_SUCCESS(Status))
298 {
299 LONG Prev = KePulseEvent(Event, EVENT_INCREMENT, FALSE);
300 ObDereferenceObject(Event);
301
302 if(PreviousState != NULL)
303 {
304 _SEH_TRY
305 {
306 *PreviousState = Prev;
307 }
308 _SEH_HANDLE
309 {
310 Status = _SEH_GetExceptionCode();
311 }
312 _SEH_END;
313 }
314 }
315
316 return Status;
317 }
318
319
320 /*
321 * @implemented
322 */
323 NTSTATUS STDCALL
324 NtQueryEvent(IN HANDLE EventHandle,
325 IN EVENT_INFORMATION_CLASS EventInformationClass,
326 OUT PVOID EventInformation,
327 IN ULONG EventInformationLength,
328 OUT PULONG ReturnLength OPTIONAL)
329 {
330 PKEVENT Event;
331 KPROCESSOR_MODE PreviousMode;
332 NTSTATUS Status = STATUS_SUCCESS;
333
334 PAGED_CODE();
335
336 PreviousMode = ExGetPreviousMode();
337
338 DefaultQueryInfoBufferCheck(EventInformationClass,
339 ExEventInfoClass,
340 EventInformation,
341 EventInformationLength,
342 ReturnLength,
343 PreviousMode,
344 &Status);
345 if(!NT_SUCCESS(Status))
346 {
347 DPRINT1("NtQueryEvent() failed, Status: 0x%x\n", Status);
348 return Status;
349 }
350
351 Status = ObReferenceObjectByHandle(EventHandle,
352 EVENT_QUERY_STATE,
353 ExEventObjectType,
354 PreviousMode,
355 (PVOID*)&Event,
356 NULL);
357 if(NT_SUCCESS(Status))
358 {
359 switch(EventInformationClass)
360 {
361 case EventBasicInformation:
362 {
363 PEVENT_BASIC_INFORMATION BasicInfo = (PEVENT_BASIC_INFORMATION)EventInformation;
364
365 _SEH_TRY
366 {
367 if (Event->Header.Type == InternalNotificationEvent)
368 BasicInfo->EventType = NotificationEvent;
369 else
370 BasicInfo->EventType = SynchronizationEvent;
371 BasicInfo->EventState = KeReadStateEvent(Event);
372
373 if(ReturnLength != NULL)
374 {
375 *ReturnLength = sizeof(EVENT_BASIC_INFORMATION);
376 }
377 }
378 _SEH_HANDLE
379 {
380 Status = _SEH_GetExceptionCode();
381 }
382 _SEH_END;
383 break;
384 }
385
386 default:
387 Status = STATUS_NOT_IMPLEMENTED;
388 break;
389 }
390
391 ObDereferenceObject(Event);
392 }
393
394 return Status;
395 }
396
397
398 /*
399 * @implemented
400 */
401 NTSTATUS STDCALL
402 NtResetEvent(IN HANDLE EventHandle,
403 OUT PLONG PreviousState OPTIONAL)
404 {
405 PKEVENT Event;
406 KPROCESSOR_MODE PreviousMode;
407 NTSTATUS Status = STATUS_SUCCESS;
408
409 PAGED_CODE();
410
411 DPRINT("NtResetEvent(EventHandle 0%x PreviousState 0%x)\n",
412 EventHandle, PreviousState);
413
414 PreviousMode = ExGetPreviousMode();
415
416 if(PreviousState != NULL && PreviousMode == UserMode)
417 {
418 _SEH_TRY
419 {
420 ProbeForWrite(PreviousState,
421 sizeof(LONG),
422 sizeof(ULONG));
423 }
424 _SEH_HANDLE
425 {
426 Status = _SEH_GetExceptionCode();
427 }
428 _SEH_END;
429
430 if(!NT_SUCCESS(Status))
431 {
432 return Status;
433 }
434 }
435
436 Status = ObReferenceObjectByHandle(EventHandle,
437 EVENT_MODIFY_STATE,
438 ExEventObjectType,
439 PreviousMode,
440 (PVOID*)&Event,
441 NULL);
442 if(NT_SUCCESS(Status))
443 {
444 LONG Prev = KeResetEvent(Event);
445 ObDereferenceObject(Event);
446
447 if(PreviousState != NULL)
448 {
449 _SEH_TRY
450 {
451 *PreviousState = Prev;
452 }
453 _SEH_HANDLE
454 {
455 Status = _SEH_GetExceptionCode();
456 }
457 _SEH_END;
458 }
459 }
460
461 return Status;
462 }
463
464
465 /*
466 * @implemented
467 */
468 NTSTATUS STDCALL
469 NtSetEvent(IN HANDLE EventHandle,
470 OUT PLONG PreviousState OPTIONAL)
471 {
472 PKEVENT Event;
473 KPROCESSOR_MODE PreviousMode;
474 NTSTATUS Status = STATUS_SUCCESS;
475
476 PAGED_CODE();
477
478 DPRINT("NtSetEvent(EventHandle 0%x PreviousState 0%x)\n",
479 EventHandle, PreviousState);
480
481 PreviousMode = ExGetPreviousMode();
482
483 if(PreviousState != NULL && PreviousMode == UserMode)
484 {
485 _SEH_TRY
486 {
487 ProbeForWrite(PreviousState,
488 sizeof(LONG),
489 sizeof(ULONG));
490 }
491 _SEH_HANDLE
492 {
493 Status = _SEH_GetExceptionCode();
494 }
495 _SEH_END;
496
497 if(!NT_SUCCESS(Status))
498 {
499 return Status;
500 }
501 }
502
503 Status = ObReferenceObjectByHandle(EventHandle,
504 EVENT_MODIFY_STATE,
505 ExEventObjectType,
506 PreviousMode,
507 (PVOID*)&Event,
508 NULL);
509 if(NT_SUCCESS(Status))
510 {
511 LONG Prev = KeSetEvent(Event, EVENT_INCREMENT, FALSE);
512 ObDereferenceObject(Event);
513
514 if(PreviousState != NULL)
515 {
516 _SEH_TRY
517 {
518 *PreviousState = Prev;
519 }
520 _SEH_HANDLE
521 {
522 Status = _SEH_GetExceptionCode();
523 }
524 _SEH_END;
525 }
526 }
527
528 return Status;
529 }
530
531
532 /*
533 * @unimplemented
534 */
535 NTSTATUS
536 STDCALL
537 NtTraceEvent(
538 IN ULONG TraceHandle,
539 IN ULONG Flags,
540 IN ULONG TraceHeaderLength,
541 IN struct _EVENT_TRACE_HEADER* TraceHeader
542 )
543 {
544 UNIMPLEMENTED;
545 return STATUS_NOT_IMPLEMENTED;
546 }
547
548
549 /* EOF */