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