Merge 13159:13510 from trunk
[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 Status = ObReferenceObjectByHandle(EventHandle,
92 EVENT_MODIFY_STATE,
93 ExEventObjectType,
94 ExGetPreviousMode(),
95 (PVOID*)&Event,
96 NULL);
97 if(NT_SUCCESS(Status))
98 {
99 KeClearEvent(Event);
100 ObDereferenceObject(Event);
101 }
102
103 return Status;
104 }
105
106
107 /*
108 * @implemented
109 */
110 NTSTATUS STDCALL
111 NtCreateEvent(OUT PHANDLE EventHandle,
112 IN ACCESS_MASK DesiredAccess,
113 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
114 IN EVENT_TYPE EventType,
115 IN BOOLEAN InitialState)
116 {
117 KPROCESSOR_MODE PreviousMode;
118 PKEVENT Event;
119 HANDLE hEvent;
120 NTSTATUS Status = STATUS_SUCCESS;
121
122 PreviousMode = ExGetPreviousMode();
123
124 if(PreviousMode == UserMode)
125 {
126 _SEH_TRY
127 {
128 ProbeForWrite(EventHandle,
129 sizeof(HANDLE),
130 sizeof(ULONG));
131 }
132 _SEH_HANDLE
133 {
134 Status = _SEH_GetExceptionCode();
135 }
136 _SEH_END;
137
138 if(!NT_SUCCESS(Status))
139 {
140 return Status;
141 }
142 }
143
144 Status = ObCreateObject(PreviousMode,
145 ExEventObjectType,
146 ObjectAttributes,
147 PreviousMode,
148 NULL,
149 sizeof(KEVENT),
150 0,
151 0,
152 (PVOID*)&Event);
153 if(NT_SUCCESS(Status))
154 {
155 KeInitializeEvent(Event,
156 EventType,
157 InitialState);
158
159
160 Status = ObInsertObject((PVOID)Event,
161 NULL,
162 DesiredAccess,
163 0,
164 NULL,
165 &hEvent);
166 ObDereferenceObject(Event);
167
168 if(NT_SUCCESS(Status))
169 {
170 _SEH_TRY
171 {
172 *EventHandle = hEvent;
173 }
174 _SEH_HANDLE
175 {
176 Status = _SEH_GetExceptionCode();
177 }
178 _SEH_END;
179 }
180 }
181
182 return Status;
183 }
184
185
186 /*
187 * @implemented
188 */
189 NTSTATUS STDCALL
190 NtOpenEvent(OUT PHANDLE EventHandle,
191 IN ACCESS_MASK DesiredAccess,
192 IN POBJECT_ATTRIBUTES ObjectAttributes)
193 {
194 HANDLE hEvent;
195 KPROCESSOR_MODE PreviousMode;
196 NTSTATUS Status = STATUS_SUCCESS;
197
198 DPRINT("NtOpenEvent(0x%x, 0x%x, 0x%x)\n", EventHandle, DesiredAccess, ObjectAttributes);
199
200 PreviousMode = ExGetPreviousMode();
201
202 if(PreviousMode == UserMode)
203 {
204 _SEH_TRY
205 {
206 ProbeForWrite(EventHandle,
207 sizeof(HANDLE),
208 sizeof(ULONG));
209 }
210 _SEH_HANDLE
211 {
212 Status = _SEH_GetExceptionCode();
213 }
214 _SEH_END;
215
216 if(!NT_SUCCESS(Status))
217 {
218 return Status;
219 }
220 }
221
222 Status = ObOpenObjectByName(ObjectAttributes,
223 ExEventObjectType,
224 NULL,
225 PreviousMode,
226 DesiredAccess,
227 NULL,
228 &hEvent);
229
230 if(NT_SUCCESS(Status))
231 {
232 _SEH_TRY
233 {
234 *EventHandle = hEvent;
235 }
236 _SEH_HANDLE
237 {
238 Status = _SEH_GetExceptionCode();
239 }
240 _SEH_END;
241 }
242
243 return Status;
244 }
245
246
247 /*
248 * @implemented
249 */
250 NTSTATUS STDCALL
251 NtPulseEvent(IN HANDLE EventHandle,
252 OUT PLONG PreviousState OPTIONAL)
253 {
254 PKEVENT Event;
255 KPROCESSOR_MODE PreviousMode;
256 NTSTATUS Status = STATUS_SUCCESS;
257
258 DPRINT("NtPulseEvent(EventHandle 0%x PreviousState 0%x)\n",
259 EventHandle, PreviousState);
260
261 PreviousMode = ExGetPreviousMode();
262
263 if(PreviousState != NULL && PreviousMode == UserMode)
264 {
265 _SEH_TRY
266 {
267 ProbeForWrite(PreviousState,
268 sizeof(LONG),
269 sizeof(ULONG));
270 }
271 _SEH_HANDLE
272 {
273 Status = _SEH_GetExceptionCode();
274 }
275 _SEH_END;
276
277 if(!NT_SUCCESS(Status))
278 {
279 return Status;
280 }
281 }
282
283 Status = ObReferenceObjectByHandle(EventHandle,
284 EVENT_MODIFY_STATE,
285 ExEventObjectType,
286 PreviousMode,
287 (PVOID*)&Event,
288 NULL);
289 if(NT_SUCCESS(Status))
290 {
291 LONG Prev = KePulseEvent(Event, EVENT_INCREMENT, FALSE);
292 ObDereferenceObject(Event);
293
294 if(PreviousState != NULL)
295 {
296 _SEH_TRY
297 {
298 *PreviousState = Prev;
299 }
300 _SEH_HANDLE
301 {
302 Status = _SEH_GetExceptionCode();
303 }
304 _SEH_END;
305 }
306 }
307
308 return Status;
309 }
310
311
312 /*
313 * @implemented
314 */
315 NTSTATUS STDCALL
316 NtQueryEvent(IN HANDLE EventHandle,
317 IN EVENT_INFORMATION_CLASS EventInformationClass,
318 OUT PVOID EventInformation,
319 IN ULONG EventInformationLength,
320 OUT PULONG ReturnLength OPTIONAL)
321 {
322 PKEVENT Event;
323 KPROCESSOR_MODE PreviousMode;
324 NTSTATUS Status = STATUS_SUCCESS;
325
326 PreviousMode = ExGetPreviousMode();
327
328 DefaultQueryInfoBufferCheck(EventInformationClass,
329 ExEventInfoClass,
330 EventInformation,
331 EventInformationLength,
332 ReturnLength,
333 PreviousMode,
334 &Status);
335 if(!NT_SUCCESS(Status))
336 {
337 DPRINT1("NtQueryEvent() failed, Status: 0x%x\n", Status);
338 return Status;
339 }
340
341 Status = ObReferenceObjectByHandle(EventHandle,
342 EVENT_QUERY_STATE,
343 ExEventObjectType,
344 PreviousMode,
345 (PVOID*)&Event,
346 NULL);
347 if(NT_SUCCESS(Status))
348 {
349 switch(EventInformationClass)
350 {
351 case EventBasicInformation:
352 {
353 PEVENT_BASIC_INFORMATION BasicInfo = (PEVENT_BASIC_INFORMATION)EventInformation;
354
355 _SEH_TRY
356 {
357 if (Event->Header.Type == InternalNotificationEvent)
358 BasicInfo->EventType = NotificationEvent;
359 else
360 BasicInfo->EventType = SynchronizationEvent;
361 BasicInfo->EventState = KeReadStateEvent(Event);
362
363 if(ReturnLength != NULL)
364 {
365 *ReturnLength = sizeof(EVENT_BASIC_INFORMATION);
366 }
367 }
368 _SEH_HANDLE
369 {
370 Status = _SEH_GetExceptionCode();
371 }
372 _SEH_END;
373 break;
374 }
375
376 default:
377 Status = STATUS_NOT_IMPLEMENTED;
378 break;
379 }
380
381 ObDereferenceObject(Event);
382 }
383
384 return Status;
385 }
386
387
388 /*
389 * @implemented
390 */
391 NTSTATUS STDCALL
392 NtResetEvent(IN HANDLE EventHandle,
393 OUT PLONG PreviousState OPTIONAL)
394 {
395 PKEVENT Event;
396 KPROCESSOR_MODE PreviousMode;
397 NTSTATUS Status = STATUS_SUCCESS;
398
399 DPRINT("NtResetEvent(EventHandle 0%x PreviousState 0%x)\n",
400 EventHandle, PreviousState);
401
402 PreviousMode = ExGetPreviousMode();
403
404 if(PreviousState != NULL && PreviousMode == UserMode)
405 {
406 _SEH_TRY
407 {
408 ProbeForWrite(PreviousState,
409 sizeof(LONG),
410 sizeof(ULONG));
411 }
412 _SEH_HANDLE
413 {
414 Status = _SEH_GetExceptionCode();
415 }
416 _SEH_END;
417
418 if(!NT_SUCCESS(Status))
419 {
420 return Status;
421 }
422 }
423
424 Status = ObReferenceObjectByHandle(EventHandle,
425 EVENT_MODIFY_STATE,
426 ExEventObjectType,
427 PreviousMode,
428 (PVOID*)&Event,
429 NULL);
430 if(NT_SUCCESS(Status))
431 {
432 LONG Prev = KeResetEvent(Event);
433 ObDereferenceObject(Event);
434
435 if(PreviousState != NULL)
436 {
437 _SEH_TRY
438 {
439 *PreviousState = Prev;
440 }
441 _SEH_HANDLE
442 {
443 Status = _SEH_GetExceptionCode();
444 }
445 _SEH_END;
446 }
447 }
448
449 return Status;
450 }
451
452
453 /*
454 * @implemented
455 */
456 NTSTATUS STDCALL
457 NtSetEvent(IN HANDLE EventHandle,
458 OUT PLONG PreviousState OPTIONAL)
459 {
460 PKEVENT Event;
461 KPROCESSOR_MODE PreviousMode;
462 NTSTATUS Status = STATUS_SUCCESS;
463
464 DPRINT("NtSetEvent(EventHandle 0%x PreviousState 0%x)\n",
465 EventHandle, PreviousState);
466
467 PreviousMode = ExGetPreviousMode();
468
469 if(PreviousState != NULL && PreviousMode == UserMode)
470 {
471 _SEH_TRY
472 {
473 ProbeForWrite(PreviousState,
474 sizeof(LONG),
475 sizeof(ULONG));
476 }
477 _SEH_HANDLE
478 {
479 Status = _SEH_GetExceptionCode();
480 }
481 _SEH_END;
482
483 if(!NT_SUCCESS(Status))
484 {
485 return Status;
486 }
487 }
488
489 Status = ObReferenceObjectByHandle(EventHandle,
490 EVENT_MODIFY_STATE,
491 ExEventObjectType,
492 PreviousMode,
493 (PVOID*)&Event,
494 NULL);
495 if(NT_SUCCESS(Status))
496 {
497 LONG Prev = KeSetEvent(Event, EVENT_INCREMENT, FALSE);
498 ObDereferenceObject(Event);
499
500 if(PreviousState != NULL)
501 {
502 _SEH_TRY
503 {
504 *PreviousState = Prev;
505 }
506 _SEH_HANDLE
507 {
508 Status = _SEH_GetExceptionCode();
509 }
510 _SEH_END;
511 }
512 }
513
514 return Status;
515 }
516
517
518 /*
519 * @unimplemented
520 */
521 NTSTATUS
522 STDCALL
523 NtTraceEvent(
524 IN ULONG TraceHandle,
525 IN ULONG Flags,
526 IN ULONG TraceHeaderLength,
527 IN struct _EVENT_TRACE_HEADER* TraceHeader
528 )
529 {
530 UNIMPLEMENTED;
531 return STATUS_NOT_IMPLEMENTED;
532 }
533
534
535 /* EOF */