888bb14e1b83a8bdc699cc5cb41d192a4aa1db3c
[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 /* 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 /* EventBasicInformation */
30 ICI_SQ_SAME( sizeof(EVENT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY),
31 };
32
33 /* FUNCTIONS *****************************************************************/
34
35 VOID
36 INIT_FUNCTION
37 STDCALL
38 ExpInitializeEventImplementation(VOID)
39 {
40 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
41 UNICODE_STRING Name;
42
43 DPRINT("Creating Event Object Type\n");
44
45 /* Create the Event Object Type */
46 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
47 RtlInitUnicodeString(&Name, L"Event");
48 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
49 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KEVENT);
50 ObjectTypeInitializer.GenericMapping = ExpEventMapping;
51 ObjectTypeInitializer.PoolType = NonPagedPool;
52 ObjectTypeInitializer.ValidAccessMask = EVENT_ALL_ACCESS;
53 ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ExEventObjectType);
54 }
55
56 /*
57 * @implemented
58 */
59 NTSTATUS
60 STDCALL
61 NtClearEvent(IN HANDLE EventHandle)
62 {
63 PKEVENT Event;
64 NTSTATUS Status;
65
66 PAGED_CODE();
67
68 /* Reference the Object */
69 Status = ObReferenceObjectByHandle(EventHandle,
70 EVENT_MODIFY_STATE,
71 ExEventObjectType,
72 ExGetPreviousMode(),
73 (PVOID*)&Event,
74 NULL);
75
76 /* Check for Success */
77 if(NT_SUCCESS(Status)) {
78
79 /* Clear the Event and Dereference */
80 KeClearEvent(Event);
81 ObDereferenceObject(Event);
82 }
83
84 /* Return Status */
85 return Status;
86 }
87
88
89 /*
90 * @implemented
91 */
92 NTSTATUS
93 STDCALL
94 NtCreateEvent(OUT PHANDLE EventHandle,
95 IN ACCESS_MASK DesiredAccess,
96 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
97 IN EVENT_TYPE EventType,
98 IN BOOLEAN InitialState)
99 {
100 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
101 PKEVENT Event;
102 HANDLE hEvent;
103 NTSTATUS Status = STATUS_SUCCESS;
104
105 PAGED_CODE();
106 DPRINT("NtCreateEvent(0x%p, 0x%x, 0x%p)\n", EventHandle, DesiredAccess, ObjectAttributes);
107
108 /* Check Output Safety */
109 if(PreviousMode != KernelMode) {
110
111 _SEH_TRY {
112
113 ProbeForWrite(EventHandle,
114 sizeof(HANDLE),
115 sizeof(ULONG));
116 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
117
118 Status = _SEH_GetExceptionCode();
119
120 } _SEH_END;
121
122 if(!NT_SUCCESS(Status)) return Status;
123 }
124
125 /* Create the Object */
126 Status = ObCreateObject(PreviousMode,
127 ExEventObjectType,
128 ObjectAttributes,
129 PreviousMode,
130 NULL,
131 sizeof(KEVENT),
132 0,
133 0,
134 (PVOID*)&Event);
135
136 /* Check for Success */
137 if(NT_SUCCESS(Status)) {
138
139 /* Initalize the Event */
140 KeInitializeEvent(Event,
141 EventType,
142 InitialState);
143
144 /* Insert it */
145 Status = ObInsertObject((PVOID)Event,
146 NULL,
147 DesiredAccess,
148 0,
149 NULL,
150 &hEvent);
151 ObDereferenceObject(Event);
152
153 /* Check for success and return handle */
154 if(NT_SUCCESS(Status)) {
155
156 _SEH_TRY {
157
158 *EventHandle = hEvent;
159
160 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
161
162 Status = _SEH_GetExceptionCode();
163
164 } _SEH_END;
165 }
166 }
167
168 /* Return Status */
169 return Status;
170 }
171
172 /*
173 * @implemented
174 */
175 NTSTATUS
176 STDCALL
177 NtOpenEvent(OUT PHANDLE EventHandle,
178 IN ACCESS_MASK DesiredAccess,
179 IN POBJECT_ATTRIBUTES ObjectAttributes)
180 {
181 HANDLE hEvent;
182 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
183 NTSTATUS Status = STATUS_SUCCESS;
184
185 PAGED_CODE();
186 DPRINT("NtOpenEvent(0x%p, 0x%x, 0x%p)\n", EventHandle, DesiredAccess, ObjectAttributes);
187
188 /* Check Output Safety */
189 if(PreviousMode != KernelMode) {
190
191 _SEH_TRY {
192
193 ProbeForWrite(EventHandle,
194 sizeof(HANDLE),
195 sizeof(ULONG));
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 == UserMode) {
250
251 _SEH_TRY {
252
253 ProbeForWrite(PreviousState,
254 sizeof(LONG),
255 sizeof(ULONG));
256 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
257
258 Status = _SEH_GetExceptionCode();
259
260 } _SEH_END;
261
262 if(!NT_SUCCESS(Status)) return Status;
263 }
264
265 /* Open the Object */
266 Status = ObReferenceObjectByHandle(EventHandle,
267 EVENT_MODIFY_STATE,
268 ExEventObjectType,
269 PreviousMode,
270 (PVOID*)&Event,
271 NULL);
272
273 /* Check for success */
274 if(NT_SUCCESS(Status)) {
275
276 /* Pulse the Event */
277 LONG Prev = KePulseEvent(Event, EVENT_INCREMENT, FALSE);
278 ObDereferenceObject(Event);
279
280 /* Return it */
281 if(PreviousState) {
282
283 _SEH_TRY {
284
285 *PreviousState = Prev;
286
287 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
288
289 Status = _SEH_GetExceptionCode();
290
291 } _SEH_END;
292 }
293 }
294
295 /* Return Status */
296 return Status;
297 }
298
299
300 /*
301 * @implemented
302 */
303 NTSTATUS
304 STDCALL
305 NtQueryEvent(IN HANDLE EventHandle,
306 IN EVENT_INFORMATION_CLASS EventInformationClass,
307 OUT PVOID EventInformation,
308 IN ULONG EventInformationLength,
309 OUT PULONG ReturnLength OPTIONAL)
310 {
311 PKEVENT Event;
312 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
313 NTSTATUS Status = STATUS_SUCCESS;
314 PEVENT_BASIC_INFORMATION BasicInfo = (PEVENT_BASIC_INFORMATION)EventInformation;
315
316 PAGED_CODE();
317 DPRINT("NtQueryEvent(0x%p, 0x%x)\n", EventHandle, EventInformationClass);
318
319 /* Check buffers and class validity */
320 DefaultQueryInfoBufferCheck(EventInformationClass,
321 ExEventInfoClass,
322 EventInformation,
323 EventInformationLength,
324 ReturnLength,
325 PreviousMode,
326 &Status);
327 if(!NT_SUCCESS(Status)) {
328
329 /* Invalid buffers */
330 DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
331 return Status;
332 }
333
334 /* Get the Object */
335 Status = ObReferenceObjectByHandle(EventHandle,
336 EVENT_QUERY_STATE,
337 ExEventObjectType,
338 PreviousMode,
339 (PVOID*)&Event,
340 NULL);
341
342 /* Check for success */
343 if(NT_SUCCESS(Status)) {
344
345 _SEH_TRY {
346
347 /* Return Event Type and State */
348 BasicInfo->EventType = Event->Header.Type;
349 BasicInfo->EventState = KeReadStateEvent(Event);
350
351 /* Return length */
352 if(ReturnLength) *ReturnLength = sizeof(EVENT_BASIC_INFORMATION);
353
354 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
355
356 Status = _SEH_GetExceptionCode();
357
358 } _SEH_END;
359
360 /* Dereference the Object */
361 ObDereferenceObject(Event);
362 }
363
364 /* Return status */
365 return Status;
366 }
367
368 /*
369 * @implemented
370 */
371 NTSTATUS
372 STDCALL
373 NtResetEvent(IN HANDLE EventHandle,
374 OUT PLONG PreviousState OPTIONAL)
375 {
376 PKEVENT Event;
377 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
378 NTSTATUS Status = STATUS_SUCCESS;
379
380 PAGED_CODE();
381 DPRINT("NtResetEvent(EventHandle 0%x PreviousState 0%x)\n",
382 EventHandle, PreviousState);
383
384 /* Check buffer validity */
385 if(PreviousState && PreviousMode == UserMode) {
386
387 _SEH_TRY {
388
389 ProbeForWrite(PreviousState,
390 sizeof(LONG),
391 sizeof(ULONG));
392 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
393
394 Status = _SEH_GetExceptionCode();
395
396 } _SEH_END;
397
398 if(!NT_SUCCESS(Status)) return Status;
399 }
400
401 /* Open the Object */
402 Status = ObReferenceObjectByHandle(EventHandle,
403 EVENT_MODIFY_STATE,
404 ExEventObjectType,
405 PreviousMode,
406 (PVOID*)&Event,
407 NULL);
408
409 /* Check for success */
410 if(NT_SUCCESS(Status)) {
411
412 /* Reset the Event */
413 LONG Prev = KeResetEvent(Event);
414 ObDereferenceObject(Event);
415
416 /* Return it */
417 if(PreviousState) {
418
419 _SEH_TRY {
420
421 *PreviousState = Prev;
422
423 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
424
425 Status = _SEH_GetExceptionCode();
426
427 } _SEH_END;
428 }
429 }
430
431 /* Return Status */
432 return Status;
433 }
434
435 /*
436 * @implemented
437 */
438 NTSTATUS
439 STDCALL
440 NtSetEvent(IN HANDLE EventHandle,
441 OUT PLONG PreviousState OPTIONAL)
442 {
443 PKEVENT Event;
444 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
445 NTSTATUS Status = STATUS_SUCCESS;
446
447 PAGED_CODE();
448 DPRINT("NtSetEvent(EventHandle 0%x PreviousState 0%x)\n",
449 EventHandle, PreviousState);
450
451 /* Check buffer validity */
452 if(PreviousState != NULL && PreviousMode == UserMode) {
453
454 _SEH_TRY {
455
456 ProbeForWrite(PreviousState,
457 sizeof(LONG),
458 sizeof(ULONG));
459 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
460
461 Status = _SEH_GetExceptionCode();
462
463 } _SEH_END;
464
465 if(!NT_SUCCESS(Status)) return Status;
466 }
467
468 /* Open the Object */
469 Status = ObReferenceObjectByHandle(EventHandle,
470 EVENT_MODIFY_STATE,
471 ExEventObjectType,
472 PreviousMode,
473 (PVOID*)&Event,
474 NULL);
475
476 /* Check for success */
477 if(NT_SUCCESS(Status)) {
478
479 /* Set the Event */
480 LONG Prev = KeSetEvent(Event, EVENT_INCREMENT, FALSE);
481 ObDereferenceObject(Event);
482
483 /* Return it */
484 if(PreviousState) {
485
486 _SEH_TRY {
487
488 *PreviousState = Prev;
489
490 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
491
492 Status = _SEH_GetExceptionCode();
493
494 } _SEH_END;
495 }
496 }
497
498 /* Return Status */
499 return Status;
500 }
501
502 /* EOF */