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