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