e798ecd7e8ada8c4206578b9b136318d7e9bd324
[reactos.git] / reactos / ntoskrnl / ex / event.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/nt/event.c
5 * PURPOSE: Named event support
6 *
7 * PROGRAMMERS: Alex Ionescu(alex@relsoft.net) - Fixed bugs/commented
8 * Philip Susi and David Welch
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 #if defined (ALLOC_PRAGMA)
18 #pragma alloc_text(INIT, ExpInitializeEventImplementation)
19 #endif
20
21 /* GLOBALS *******************************************************************/
22
23 POBJECT_TYPE ExEventObjectType = NULL;
24
25 static GENERIC_MAPPING ExpEventMapping = {
26 STANDARD_RIGHTS_READ | SYNCHRONIZE | EVENT_QUERY_STATE,
27 STANDARD_RIGHTS_WRITE | SYNCHRONIZE | EVENT_MODIFY_STATE,
28 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | EVENT_QUERY_STATE,
29 EVENT_ALL_ACCESS};
30
31 static const INFORMATION_CLASS_INFO ExEventInfoClass[] = {
32
33 /* EventBasicInformation */
34 ICI_SQ_SAME( sizeof(EVENT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY),
35 };
36
37 /* FUNCTIONS *****************************************************************/
38
39 VOID
40 INIT_FUNCTION
41 STDCALL
42 ExpInitializeEventImplementation(VOID)
43 {
44 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
45 UNICODE_STRING Name;
46
47 DPRINT("Creating Event Object Type\n");
48
49 /* Create the Event Object Type */
50 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
51 RtlInitUnicodeString(&Name, L"Event");
52 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
53 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KEVENT);
54 ObjectTypeInitializer.GenericMapping = ExpEventMapping;
55 ObjectTypeInitializer.PoolType = NonPagedPool;
56 ObjectTypeInitializer.ValidAccessMask = EVENT_ALL_ACCESS;
57 ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ExEventObjectType);
58 }
59
60 /*
61 * @implemented
62 */
63 NTSTATUS
64 STDCALL
65 NtClearEvent(IN HANDLE EventHandle)
66 {
67 PKEVENT Event;
68 NTSTATUS Status;
69
70 PAGED_CODE();
71
72 /* Reference the Object */
73 Status = ObReferenceObjectByHandle(EventHandle,
74 EVENT_MODIFY_STATE,
75 ExEventObjectType,
76 ExGetPreviousMode(),
77 (PVOID*)&Event,
78 NULL);
79
80 /* Check for Success */
81 if(NT_SUCCESS(Status)) {
82
83 /* Clear the Event and Dereference */
84 KeClearEvent(Event);
85 ObDereferenceObject(Event);
86 }
87
88 /* Return Status */
89 return Status;
90 }
91
92
93 /*
94 * @implemented
95 */
96 NTSTATUS
97 STDCALL
98 NtCreateEvent(OUT PHANDLE EventHandle,
99 IN ACCESS_MASK DesiredAccess,
100 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
101 IN EVENT_TYPE EventType,
102 IN BOOLEAN InitialState)
103 {
104 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
105 PKEVENT Event;
106 HANDLE hEvent;
107 NTSTATUS Status = STATUS_SUCCESS;
108
109 PAGED_CODE();
110 DPRINT("NtCreateEvent(0x%p, 0x%x, 0x%p)\n", EventHandle, DesiredAccess, ObjectAttributes);
111
112 /* Check Output Safety */
113 if(PreviousMode != KernelMode) {
114
115 _SEH_TRY {
116
117 ProbeForWriteHandle(EventHandle);
118 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
119
120 Status = _SEH_GetExceptionCode();
121
122 } _SEH_END;
123
124 if(!NT_SUCCESS(Status)) return Status;
125 }
126
127 /* Create the Object */
128 Status = ObCreateObject(PreviousMode,
129 ExEventObjectType,
130 ObjectAttributes,
131 PreviousMode,
132 NULL,
133 sizeof(KEVENT),
134 0,
135 0,
136 (PVOID*)&Event);
137
138 /* Check for Success */
139 if(NT_SUCCESS(Status)) {
140
141 /* Initalize the Event */
142 KeInitializeEvent(Event,
143 EventType,
144 InitialState);
145
146 /* Insert it */
147 Status = ObInsertObject((PVOID)Event,
148 NULL,
149 DesiredAccess,
150 0,
151 NULL,
152 &hEvent);
153 ObDereferenceObject(Event);
154
155 /* Check for success and return handle */
156 if(NT_SUCCESS(Status)) {
157
158 _SEH_TRY {
159
160 *EventHandle = hEvent;
161
162 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
163
164 Status = _SEH_GetExceptionCode();
165
166 } _SEH_END;
167 }
168 }
169
170 /* Return Status */
171 return Status;
172 }
173
174 /*
175 * @implemented
176 */
177 NTSTATUS
178 STDCALL
179 NtOpenEvent(OUT PHANDLE EventHandle,
180 IN ACCESS_MASK DesiredAccess,
181 IN POBJECT_ATTRIBUTES ObjectAttributes)
182 {
183 HANDLE hEvent;
184 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
185 NTSTATUS Status = STATUS_SUCCESS;
186
187 PAGED_CODE();
188 DPRINT("NtOpenEvent(0x%p, 0x%x, 0x%p)\n", EventHandle, DesiredAccess, ObjectAttributes);
189
190 /* Check Output Safety */
191 if(PreviousMode != KernelMode) {
192
193 _SEH_TRY {
194
195 ProbeForWriteHandle(EventHandle);
196 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
197
198 Status = _SEH_GetExceptionCode();
199
200 } _SEH_END;
201
202 if(!NT_SUCCESS(Status)) return Status;
203 }
204
205 /* Open the Object */
206 Status = ObOpenObjectByName(ObjectAttributes,
207 ExEventObjectType,
208 NULL,
209 PreviousMode,
210 DesiredAccess,
211 NULL,
212 &hEvent);
213
214 /* Check for success and return handle */
215 if(NT_SUCCESS(Status)) {
216
217 _SEH_TRY {
218
219 *EventHandle = hEvent;
220
221 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
222
223 Status = _SEH_GetExceptionCode();
224
225 } _SEH_END;
226 }
227
228 /* Return status */
229 return Status;
230 }
231
232 /*
233 * @implemented
234 */
235 NTSTATUS
236 STDCALL
237 NtPulseEvent(IN HANDLE EventHandle,
238 OUT PLONG PreviousState OPTIONAL)
239 {
240 PKEVENT Event;
241 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
242 NTSTATUS Status = STATUS_SUCCESS;
243
244 PAGED_CODE();
245 DPRINT("NtPulseEvent(EventHandle 0%x PreviousState 0%x)\n",
246 EventHandle, PreviousState);
247
248 /* Check buffer validity */
249 if(PreviousState && PreviousMode != KernelMode) {
250
251 _SEH_TRY {
252
253 ProbeForWriteLong(PreviousState);
254 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
255
256 Status = _SEH_GetExceptionCode();
257
258 } _SEH_END;
259
260 if(!NT_SUCCESS(Status)) return Status;
261 }
262
263 /* Open the Object */
264 Status = ObReferenceObjectByHandle(EventHandle,
265 EVENT_MODIFY_STATE,
266 ExEventObjectType,
267 PreviousMode,
268 (PVOID*)&Event,
269 NULL);
270
271 /* Check for success */
272 if(NT_SUCCESS(Status)) {
273
274 /* Pulse the Event */
275 LONG Prev = KePulseEvent(Event, EVENT_INCREMENT, FALSE);
276 ObDereferenceObject(Event);
277
278 /* Return it */
279 if(PreviousState) {
280
281 _SEH_TRY {
282
283 *PreviousState = Prev;
284
285 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
286
287 Status = _SEH_GetExceptionCode();
288
289 } _SEH_END;
290 }
291 }
292
293 /* Return Status */
294 return Status;
295 }
296
297
298 /*
299 * @implemented
300 */
301 NTSTATUS
302 STDCALL
303 NtQueryEvent(IN HANDLE EventHandle,
304 IN EVENT_INFORMATION_CLASS EventInformationClass,
305 OUT PVOID EventInformation,
306 IN ULONG EventInformationLength,
307 OUT PULONG ReturnLength OPTIONAL)
308 {
309 PKEVENT Event;
310 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
311 NTSTATUS Status = STATUS_SUCCESS;
312 PEVENT_BASIC_INFORMATION BasicInfo = (PEVENT_BASIC_INFORMATION)EventInformation;
313
314 PAGED_CODE();
315 DPRINT("NtQueryEvent(0x%p, 0x%x)\n", EventHandle, EventInformationClass);
316
317 /* Check buffers and class validity */
318 Status = DefaultQueryInfoBufferCheck(EventInformationClass,
319 ExEventInfoClass,
320 sizeof(ExEventInfoClass) / sizeof(ExEventInfoClass[0]),
321 EventInformation,
322 EventInformationLength,
323 ReturnLength,
324 PreviousMode);
325 if(!NT_SUCCESS(Status)) {
326
327 /* Invalid buffers */
328 DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
329 return Status;
330 }
331
332 /* Get the Object */
333 Status = ObReferenceObjectByHandle(EventHandle,
334 EVENT_QUERY_STATE,
335 ExEventObjectType,
336 PreviousMode,
337 (PVOID*)&Event,
338 NULL);
339
340 /* Check for success */
341 if(NT_SUCCESS(Status)) {
342
343 _SEH_TRY {
344
345 /* Return Event Type and State */
346 BasicInfo->EventType = Event->Header.Type;
347 BasicInfo->EventState = KeReadStateEvent(Event);
348
349 /* Return length */
350 if(ReturnLength) *ReturnLength = sizeof(EVENT_BASIC_INFORMATION);
351
352 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
353
354 Status = _SEH_GetExceptionCode();
355
356 } _SEH_END;
357
358 /* Dereference the Object */
359 ObDereferenceObject(Event);
360 }
361
362 /* Return status */
363 return Status;
364 }
365
366 /*
367 * @implemented
368 */
369 NTSTATUS
370 STDCALL
371 NtResetEvent(IN HANDLE EventHandle,
372 OUT PLONG PreviousState OPTIONAL)
373 {
374 PKEVENT Event;
375 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
376 NTSTATUS Status = STATUS_SUCCESS;
377
378 PAGED_CODE();
379 DPRINT("NtResetEvent(EventHandle 0%x PreviousState 0%x)\n",
380 EventHandle, PreviousState);
381
382 /* Check buffer validity */
383 if(PreviousState && PreviousMode != KernelMode) {
384
385 _SEH_TRY {
386
387 ProbeForWriteLong(PreviousState);
388 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
389
390 Status = _SEH_GetExceptionCode();
391
392 } _SEH_END;
393
394 if(!NT_SUCCESS(Status)) return Status;
395 }
396
397 /* Open the Object */
398 Status = ObReferenceObjectByHandle(EventHandle,
399 EVENT_MODIFY_STATE,
400 ExEventObjectType,
401 PreviousMode,
402 (PVOID*)&Event,
403 NULL);
404
405 /* Check for success */
406 if(NT_SUCCESS(Status)) {
407
408 /* Reset the Event */
409 LONG Prev = KeResetEvent(Event);
410 ObDereferenceObject(Event);
411
412 /* Return it */
413 if(PreviousState) {
414
415 _SEH_TRY {
416
417 *PreviousState = Prev;
418
419 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
420
421 Status = _SEH_GetExceptionCode();
422
423 } _SEH_END;
424 }
425 }
426
427 /* Return Status */
428 return Status;
429 }
430
431 /*
432 * @implemented
433 */
434 NTSTATUS
435 STDCALL
436 NtSetEvent(IN HANDLE EventHandle,
437 OUT PLONG PreviousState OPTIONAL)
438 {
439 PKEVENT Event;
440 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
441 NTSTATUS Status = STATUS_SUCCESS;
442
443 PAGED_CODE();
444 DPRINT("NtSetEvent(EventHandle 0%x PreviousState 0%x)\n",
445 EventHandle, PreviousState);
446
447 /* Check buffer validity */
448 if(PreviousState != NULL && PreviousMode != KernelMode) {
449
450 _SEH_TRY {
451
452 ProbeForWriteLong(PreviousState);
453 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
454
455 Status = _SEH_GetExceptionCode();
456
457 } _SEH_END;
458
459 if(!NT_SUCCESS(Status)) return Status;
460 }
461
462 /* Open the Object */
463 Status = ObReferenceObjectByHandle(EventHandle,
464 EVENT_MODIFY_STATE,
465 ExEventObjectType,
466 PreviousMode,
467 (PVOID*)&Event,
468 NULL);
469
470 /* Check for success */
471 if(NT_SUCCESS(Status)) {
472
473 /* Set the Event */
474 LONG Prev = KeSetEvent(Event, EVENT_INCREMENT, FALSE);
475 ObDereferenceObject(Event);
476
477 /* Return it */
478 if(PreviousState) {
479
480 _SEH_TRY {
481
482 *PreviousState = Prev;
483
484 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
485
486 Status = _SEH_GetExceptionCode();
487
488 } _SEH_END;
489 }
490 }
491
492 /* Return Status */
493 return Status;
494 }
495
496 /* EOF */