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