merge ROS Shell without integrated explorer part into trunk
[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 ExpInitializeEventImplementation(VOID)
38 {
39 /* Create the Event Object Type */
40 ExEventObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
41 RtlInitUnicodeString(&ExEventObjectType->TypeName, L"Event");
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 DPRINT("NtCreateEvent(0x%x, 0x%x, 0x%x)\n", EventHandle, DesiredAccess, ObjectAttributes);
114
115 /* Check Output Safety */
116 if(PreviousMode != KernelMode) {
117
118 _SEH_TRY {
119
120 ProbeForWrite(EventHandle,
121 sizeof(HANDLE),
122 sizeof(ULONG));
123 } _SEH_HANDLE {
124
125 Status = _SEH_GetExceptionCode();
126
127 } _SEH_END;
128
129 if(!NT_SUCCESS(Status)) return Status;
130 }
131
132 /* Create the Object */
133 Status = ObCreateObject(PreviousMode,
134 ExEventObjectType,
135 ObjectAttributes,
136 PreviousMode,
137 NULL,
138 sizeof(KEVENT),
139 0,
140 0,
141 (PVOID*)&Event);
142
143 /* Check for Success */
144 if(NT_SUCCESS(Status)) {
145
146 /* Initalize the Event */
147 KeInitializeEvent(Event,
148 EventType,
149 InitialState);
150
151 /* Insert it */
152 Status = ObInsertObject((PVOID)Event,
153 NULL,
154 DesiredAccess,
155 0,
156 NULL,
157 &hEvent);
158 ObDereferenceObject(Event);
159
160 /* Check for success and return handle */
161 if(NT_SUCCESS(Status)) {
162
163 _SEH_TRY {
164
165 *EventHandle = hEvent;
166
167 } _SEH_HANDLE {
168
169 Status = _SEH_GetExceptionCode();
170
171 } _SEH_END;
172 }
173 }
174
175 /* Return Status */
176 return Status;
177 }
178
179 /*
180 * @implemented
181 */
182 NTSTATUS
183 STDCALL
184 NtOpenEvent(OUT PHANDLE EventHandle,
185 IN ACCESS_MASK DesiredAccess,
186 IN POBJECT_ATTRIBUTES ObjectAttributes)
187 {
188 HANDLE hEvent;
189 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
190 NTSTATUS Status = STATUS_SUCCESS;
191
192 PAGED_CODE();
193 DPRINT("NtOpenEvent(0x%x, 0x%x, 0x%x)\n", EventHandle, DesiredAccess, ObjectAttributes);
194
195 /* Check Output Safety */
196 if(PreviousMode != KernelMode) {
197
198 _SEH_TRY {
199
200 ProbeForWrite(EventHandle,
201 sizeof(HANDLE),
202 sizeof(ULONG));
203 } _SEH_HANDLE {
204
205 Status = _SEH_GetExceptionCode();
206
207 } _SEH_END;
208
209 if(!NT_SUCCESS(Status)) return Status;
210 }
211
212 /* Open the Object */
213 Status = ObOpenObjectByName(ObjectAttributes,
214 ExEventObjectType,
215 NULL,
216 PreviousMode,
217 DesiredAccess,
218 NULL,
219 &hEvent);
220
221 /* Check for success and return handle */
222 if(NT_SUCCESS(Status)) {
223
224 _SEH_TRY {
225
226 *EventHandle = hEvent;
227
228 } _SEH_HANDLE {
229
230 Status = _SEH_GetExceptionCode();
231
232 } _SEH_END;
233 }
234
235 /* Return status */
236 return Status;
237 }
238
239 /*
240 * @implemented
241 */
242 NTSTATUS
243 STDCALL
244 NtPulseEvent(IN HANDLE EventHandle,
245 OUT PLONG PreviousState OPTIONAL)
246 {
247 PKEVENT Event;
248 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
249 NTSTATUS Status = STATUS_SUCCESS;
250
251 PAGED_CODE();
252 DPRINT("NtPulseEvent(EventHandle 0%x PreviousState 0%x)\n",
253 EventHandle, PreviousState);
254
255 /* Check buffer validity */
256 if(PreviousState && PreviousMode == UserMode) {
257
258 _SEH_TRY {
259
260 ProbeForWrite(PreviousState,
261 sizeof(LONG),
262 sizeof(ULONG));
263 } _SEH_HANDLE {
264
265 Status = _SEH_GetExceptionCode();
266
267 } _SEH_END;
268
269 if(!NT_SUCCESS(Status)) return Status;
270 }
271
272 /* Open the Object */
273 Status = ObReferenceObjectByHandle(EventHandle,
274 EVENT_MODIFY_STATE,
275 ExEventObjectType,
276 PreviousMode,
277 (PVOID*)&Event,
278 NULL);
279
280 /* Check for success */
281 if(NT_SUCCESS(Status)) {
282
283 /* Pulse the Event */
284 LONG Prev = KePulseEvent(Event, EVENT_INCREMENT, FALSE);
285 ObDereferenceObject(Event);
286
287 /* Return it */
288 if(PreviousState) {
289
290 _SEH_TRY {
291
292 *PreviousState = Prev;
293
294 } _SEH_HANDLE {
295
296 Status = _SEH_GetExceptionCode();
297
298 } _SEH_END;
299 }
300 }
301
302 /* Return Status */
303 return Status;
304 }
305
306
307 /*
308 * @implemented
309 */
310 NTSTATUS
311 STDCALL
312 NtQueryEvent(IN HANDLE EventHandle,
313 IN EVENT_INFORMATION_CLASS EventInformationClass,
314 OUT PVOID EventInformation,
315 IN ULONG EventInformationLength,
316 OUT PULONG ReturnLength OPTIONAL)
317 {
318 PKEVENT Event;
319 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
320 NTSTATUS Status = STATUS_SUCCESS;
321 PEVENT_BASIC_INFORMATION BasicInfo = (PEVENT_BASIC_INFORMATION)EventInformation;
322
323 PAGED_CODE();
324 DPRINT("NtQueryEvent(0x%x, 0x%x, 0x%x)\n", EventHandle, EventInformationClass);
325
326 /* Check buffers and class validity */
327 DefaultQueryInfoBufferCheck(EventInformationClass,
328 ExEventInfoClass,
329 EventInformation,
330 EventInformationLength,
331 ReturnLength,
332 PreviousMode,
333 &Status);
334 if(!NT_SUCCESS(Status)) {
335
336 /* Invalid buffers */
337 DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
338 return Status;
339 }
340
341 /* Get the Object */
342 Status = ObReferenceObjectByHandle(EventHandle,
343 EVENT_QUERY_STATE,
344 ExEventObjectType,
345 PreviousMode,
346 (PVOID*)&Event,
347 NULL);
348
349 /* Check for success */
350 if(NT_SUCCESS(Status)) {
351
352 _SEH_TRY {
353
354 /* Return Event Type and State */
355 BasicInfo->EventType = Event->Header.Type;
356 BasicInfo->EventState = KeReadStateEvent(Event);
357
358 /* Return length */
359 if(ReturnLength) *ReturnLength = sizeof(EVENT_BASIC_INFORMATION);
360
361 } _SEH_HANDLE {
362
363 Status = _SEH_GetExceptionCode();
364
365 } _SEH_END;
366
367 /* Dereference the Object */
368 ObDereferenceObject(Event);
369 }
370
371 /* Return status */
372 return Status;
373 }
374
375 /*
376 * @implemented
377 */
378 NTSTATUS
379 STDCALL
380 NtResetEvent(IN HANDLE EventHandle,
381 OUT PLONG PreviousState OPTIONAL)
382 {
383 PKEVENT Event;
384 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
385 NTSTATUS Status = STATUS_SUCCESS;
386
387 PAGED_CODE();
388 DPRINT("NtResetEvent(EventHandle 0%x PreviousState 0%x)\n",
389 EventHandle, PreviousState);
390
391 /* Check buffer validity */
392 if(PreviousState && PreviousMode == UserMode) {
393
394 _SEH_TRY {
395
396 ProbeForWrite(PreviousState,
397 sizeof(LONG),
398 sizeof(ULONG));
399 } _SEH_HANDLE {
400
401 Status = _SEH_GetExceptionCode();
402
403 } _SEH_END;
404
405 if(!NT_SUCCESS(Status)) return Status;
406 }
407
408 /* Open the Object */
409 Status = ObReferenceObjectByHandle(EventHandle,
410 EVENT_MODIFY_STATE,
411 ExEventObjectType,
412 PreviousMode,
413 (PVOID*)&Event,
414 NULL);
415
416 /* Check for success */
417 if(NT_SUCCESS(Status)) {
418
419 /* Reset the Event */
420 LONG Prev = KeResetEvent(Event);
421 ObDereferenceObject(Event);
422
423 /* Return it */
424 if(PreviousState) {
425
426 _SEH_TRY {
427
428 *PreviousState = Prev;
429
430 } _SEH_HANDLE {
431
432 Status = _SEH_GetExceptionCode();
433
434 } _SEH_END;
435 }
436 }
437
438 /* Return Status */
439 return Status;
440 }
441
442 /*
443 * @implemented
444 */
445 NTSTATUS
446 STDCALL
447 NtSetEvent(IN HANDLE EventHandle,
448 OUT PLONG PreviousState OPTIONAL)
449 {
450 PKEVENT Event;
451 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
452 NTSTATUS Status = STATUS_SUCCESS;
453
454 PAGED_CODE();
455 DPRINT("NtSetEvent(EventHandle 0%x PreviousState 0%x)\n",
456 EventHandle, PreviousState);
457
458 /* Check buffer validity */
459 if(PreviousState != NULL && PreviousMode == UserMode) {
460
461 _SEH_TRY {
462
463 ProbeForWrite(PreviousState,
464 sizeof(LONG),
465 sizeof(ULONG));
466 } _SEH_HANDLE {
467
468 Status = _SEH_GetExceptionCode();
469
470 } _SEH_END;
471
472 if(!NT_SUCCESS(Status)) return Status;
473 }
474
475 /* Open the Object */
476 Status = ObReferenceObjectByHandle(EventHandle,
477 EVENT_MODIFY_STATE,
478 ExEventObjectType,
479 PreviousMode,
480 (PVOID*)&Event,
481 NULL);
482
483 /* Check for success */
484 if(NT_SUCCESS(Status)) {
485
486 /* Set the Event */
487 LONG Prev = KeSetEvent(Event, EVENT_INCREMENT, FALSE);
488 ObDereferenceObject(Event);
489
490 /* Return it */
491 if(PreviousState) {
492
493 _SEH_TRY {
494
495 *PreviousState = Prev;
496
497 } _SEH_HANDLE {
498
499 Status = _SEH_GetExceptionCode();
500
501 } _SEH_END;
502 }
503 }
504
505 /* Return Status */
506 return Status;
507 }
508
509 /* EOF */