1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Kernel 4 * FILE: ntoskrnl/ex/event.c 5 * PURPOSE: Event support 6 * PROGRAMMERS: Alex Ionescu(alex@relsoft.net) 7 * Thomas Weidenmueller 8 */ 9 10 /* INCLUDES *****************************************************************/ 11 12 #include <ntoskrnl.h> 13 #define NDEBUG 14 #include <debug.h> 15 16 /* GLOBALS *******************************************************************/ 17 18 POBJECT_TYPE ExEventObjectType = NULL; 19 20 GENERIC_MAPPING ExpEventMapping = 21 { 22 STANDARD_RIGHTS_READ | EVENT_QUERY_STATE, 23 STANDARD_RIGHTS_WRITE | EVENT_MODIFY_STATE, 24 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, 25 EVENT_ALL_ACCESS 26 }; 27 28 static const INFORMATION_CLASS_INFO ExEventInfoClass[] = 29 { 30 /* EventBasicInformation */ 31 IQS_SAME(EVENT_BASIC_INFORMATION, ULONG, ICIF_QUERY), 32 }; 33 34 /* FUNCTIONS *****************************************************************/ 35 36 CODE_SEG("INIT") 37 BOOLEAN 38 NTAPI 39 ExpInitializeEventImplementation(VOID) 40 { 41 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; 42 UNICODE_STRING Name; 43 NTSTATUS Status; 44 DPRINT("Creating Event Object Type\n"); 45 46 /* Create the Event Object Type */ 47 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); 48 RtlInitUnicodeString(&Name, L"Event"); 49 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); 50 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KEVENT); 51 ObjectTypeInitializer.GenericMapping = ExpEventMapping; 52 ObjectTypeInitializer.PoolType = NonPagedPool; 53 ObjectTypeInitializer.ValidAccessMask = EVENT_ALL_ACCESS; 54 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK; 55 Status = ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ExEventObjectType); 56 if (!NT_SUCCESS(Status)) return FALSE; 57 return TRUE; 58 } 59 60 /* 61 * @implemented 62 */ 63 NTSTATUS 64 NTAPI 65 NtClearEvent(IN HANDLE EventHandle) 66 { 67 PKEVENT Event; 68 NTSTATUS Status; 69 PAGED_CODE(); 70 71 /* Reference the Object */ 72 Status = ObReferenceObjectByHandle(EventHandle, 73 EVENT_MODIFY_STATE, 74 ExEventObjectType, 75 ExGetPreviousMode(), 76 (PVOID*)&Event, 77 NULL); 78 79 /* Check for Success */ 80 if(NT_SUCCESS(Status)) 81 { 82 /* Clear the Event and Dereference */ 83 KeClearEvent(Event); 84 ObDereferenceObject(Event); 85 } 86 87 /* Return Status */ 88 return Status; 89 } 90 91 /* 92 * @implemented 93 */ 94 NTSTATUS 95 NTAPI 96 NtCreateEvent(OUT PHANDLE EventHandle, 97 IN ACCESS_MASK DesiredAccess, 98 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, 99 IN EVENT_TYPE EventType, 100 IN BOOLEAN InitialState) 101 { 102 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 103 PKEVENT Event; 104 HANDLE hEvent; 105 NTSTATUS Status; 106 PAGED_CODE(); 107 DPRINT("NtCreateEvent(0x%p, 0x%x, 0x%p)\n", 108 EventHandle, DesiredAccess, ObjectAttributes); 109 110 /* Check if we were called from user-mode */ 111 if (PreviousMode != KernelMode) 112 { 113 /* Enter SEH Block */ 114 _SEH2_TRY 115 { 116 /* Check handle pointer */ 117 ProbeForWriteHandle(EventHandle); 118 } 119 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 120 { 121 /* Return the exception code */ 122 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 123 } 124 _SEH2_END; 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 /* Initialize 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 154 /* Check for success */ 155 if (NT_SUCCESS(Status)) 156 { 157 /* Enter SEH for return */ 158 _SEH2_TRY 159 { 160 /* Return the handle to the caller */ 161 *EventHandle = hEvent; 162 } 163 _SEH2_EXCEPT(ExSystemExceptionFilter()) 164 { 165 /* Get the exception code */ 166 Status = _SEH2_GetExceptionCode(); 167 } 168 _SEH2_END; 169 } 170 } 171 172 /* Return Status */ 173 return Status; 174 } 175 176 /* 177 * @implemented 178 */ 179 NTSTATUS 180 NTAPI 181 NtOpenEvent(OUT PHANDLE EventHandle, 182 IN ACCESS_MASK DesiredAccess, 183 IN POBJECT_ATTRIBUTES ObjectAttributes) 184 { 185 HANDLE hEvent; 186 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 187 NTSTATUS Status; 188 PAGED_CODE(); 189 DPRINT("NtOpenEvent(0x%p, 0x%x, 0x%p)\n", 190 EventHandle, DesiredAccess, ObjectAttributes); 191 192 /* Check if we were called from user-mode */ 193 if (PreviousMode != KernelMode) 194 { 195 /* Enter SEH Block */ 196 _SEH2_TRY 197 { 198 /* Check handle pointer */ 199 ProbeForWriteHandle(EventHandle); 200 } 201 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 202 { 203 /* Return the exception code */ 204 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 205 } 206 _SEH2_END; 207 } 208 209 /* Open the Object */ 210 Status = ObOpenObjectByName(ObjectAttributes, 211 ExEventObjectType, 212 PreviousMode, 213 NULL, 214 DesiredAccess, 215 NULL, 216 &hEvent); 217 218 /* Check for success */ 219 if (NT_SUCCESS(Status)) 220 { 221 /* Enter SEH for return */ 222 _SEH2_TRY 223 { 224 /* Return the handle to the caller */ 225 *EventHandle = hEvent; 226 } 227 _SEH2_EXCEPT(ExSystemExceptionFilter()) 228 { 229 /* Get the exception code */ 230 Status = _SEH2_GetExceptionCode(); 231 } 232 _SEH2_END; 233 } 234 235 /* Return status */ 236 return Status; 237 } 238 239 /* 240 * @implemented 241 */ 242 NTSTATUS 243 NTAPI 244 NtPulseEvent(IN HANDLE EventHandle, 245 OUT PLONG PreviousState OPTIONAL) 246 { 247 PKEVENT Event; 248 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 249 NTSTATUS Status; 250 PAGED_CODE(); 251 DPRINT("NtPulseEvent(EventHandle 0%p PreviousState 0%p)\n", 252 EventHandle, PreviousState); 253 254 /* Check if we were called from user-mode */ 255 if((PreviousState) && (PreviousMode != KernelMode)) 256 { 257 /* Entry SEH Block */ 258 _SEH2_TRY 259 { 260 /* Make sure the state pointer is valid */ 261 ProbeForWriteLong(PreviousState); 262 } 263 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 264 { 265 /* Return the exception code */ 266 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 267 } 268 _SEH2_END; 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 /* Check if caller wants the old state back */ 287 if(PreviousState) 288 { 289 /* Entry SEH Block for return */ 290 _SEH2_TRY 291 { 292 /* Return previous state */ 293 *PreviousState = Prev; 294 } 295 _SEH2_EXCEPT(ExSystemExceptionFilter()) 296 { 297 /* Get the exception code */ 298 Status = _SEH2_GetExceptionCode(); 299 } 300 _SEH2_END; 301 } 302 } 303 304 /* Return Status */ 305 return Status; 306 } 307 308 /* 309 * @implemented 310 */ 311 NTSTATUS 312 NTAPI 313 NtQueryEvent(IN HANDLE EventHandle, 314 IN EVENT_INFORMATION_CLASS EventInformationClass, 315 OUT PVOID EventInformation, 316 IN ULONG EventInformationLength, 317 OUT PULONG ReturnLength OPTIONAL) 318 { 319 PKEVENT Event; 320 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 321 NTSTATUS Status; 322 PEVENT_BASIC_INFORMATION BasicInfo = 323 (PEVENT_BASIC_INFORMATION)EventInformation; 324 PAGED_CODE(); 325 DPRINT("NtQueryEvent(0x%p, 0x%x)\n", EventHandle, EventInformationClass); 326 327 /* Check buffers and class validity */ 328 Status = DefaultQueryInfoBufferCheck(EventInformationClass, 329 ExEventInfoClass, 330 sizeof(ExEventInfoClass) / 331 sizeof(ExEventInfoClass[0]), 332 ICIF_PROBE_READ_WRITE, 333 EventInformation, 334 EventInformationLength, 335 ReturnLength, 336 NULL, 337 PreviousMode); 338 if(!NT_SUCCESS(Status)) 339 { 340 /* Invalid buffers */ 341 DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status); 342 return Status; 343 } 344 345 /* Get the Object */ 346 Status = ObReferenceObjectByHandle(EventHandle, 347 EVENT_QUERY_STATE, 348 ExEventObjectType, 349 PreviousMode, 350 (PVOID*)&Event, 351 NULL); 352 353 /* Check for success */ 354 if(NT_SUCCESS(Status)) 355 { 356 /* Entry SEH Block */ 357 _SEH2_TRY 358 { 359 /* Return Event Type and State */ 360 BasicInfo->EventType = Event->Header.Type; 361 BasicInfo->EventState = KeReadStateEvent(Event); 362 363 /* Return length */ 364 if(ReturnLength) *ReturnLength = sizeof(EVENT_BASIC_INFORMATION); 365 } 366 _SEH2_EXCEPT(ExSystemExceptionFilter()) 367 { 368 /* Get the exception code */ 369 Status = _SEH2_GetExceptionCode(); 370 } 371 _SEH2_END; 372 373 /* Dereference the Object */ 374 ObDereferenceObject(Event); 375 } 376 377 /* Return status */ 378 return Status; 379 } 380 381 /* 382 * @implemented 383 */ 384 NTSTATUS 385 NTAPI 386 NtResetEvent(IN HANDLE EventHandle, 387 OUT PLONG PreviousState OPTIONAL) 388 { 389 PKEVENT Event; 390 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 391 NTSTATUS Status; 392 PAGED_CODE(); 393 DPRINT("NtResetEvent(EventHandle 0%p PreviousState 0%p)\n", 394 EventHandle, PreviousState); 395 396 /* Check if we were called from user-mode */ 397 if ((PreviousState) && (PreviousMode != KernelMode)) 398 { 399 /* Entry SEH Block */ 400 _SEH2_TRY 401 { 402 /* Make sure the state pointer is valid */ 403 ProbeForWriteLong(PreviousState); 404 } 405 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 406 { 407 /* Return the exception code */ 408 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 409 } 410 _SEH2_END; 411 } 412 413 /* Open the Object */ 414 Status = ObReferenceObjectByHandle(EventHandle, 415 EVENT_MODIFY_STATE, 416 ExEventObjectType, 417 PreviousMode, 418 (PVOID*)&Event, 419 NULL); 420 421 /* Check for success */ 422 if(NT_SUCCESS(Status)) 423 { 424 /* Reset the Event */ 425 LONG Prev = KeResetEvent(Event); 426 ObDereferenceObject(Event); 427 428 /* Check if caller wants the old state back */ 429 if(PreviousState) 430 { 431 /* Entry SEH Block for return */ 432 _SEH2_TRY 433 { 434 /* Return previous state */ 435 *PreviousState = Prev; 436 } 437 _SEH2_EXCEPT(ExSystemExceptionFilter()) 438 { 439 /* Get the exception code */ 440 Status = _SEH2_GetExceptionCode(); 441 } 442 _SEH2_END; 443 } 444 } 445 446 /* Return Status */ 447 return Status; 448 } 449 450 /* 451 * @implemented 452 */ 453 NTSTATUS 454 NTAPI 455 NtSetEvent(IN HANDLE EventHandle, 456 OUT PLONG PreviousState OPTIONAL) 457 { 458 PKEVENT Event; 459 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 460 NTSTATUS Status; 461 PAGED_CODE(); 462 DPRINT("NtSetEvent(EventHandle 0%p PreviousState 0%p)\n", 463 EventHandle, PreviousState); 464 465 /* Check if we were called from user-mode */ 466 if ((PreviousState) && (PreviousMode != KernelMode)) 467 { 468 /* Entry SEH Block */ 469 _SEH2_TRY 470 { 471 /* Make sure the state pointer is valid */ 472 ProbeForWriteLong(PreviousState); 473 } 474 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 475 { 476 /* Return the exception code */ 477 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 478 } 479 _SEH2_END; 480 } 481 482 /* Open the Object */ 483 Status = ObReferenceObjectByHandle(EventHandle, 484 EVENT_MODIFY_STATE, 485 ExEventObjectType, 486 PreviousMode, 487 (PVOID*)&Event, 488 NULL); 489 if (NT_SUCCESS(Status)) 490 { 491 /* Set the Event */ 492 LONG Prev = KeSetEvent(Event, EVENT_INCREMENT, FALSE); 493 ObDereferenceObject(Event); 494 495 /* Check if caller wants the old state back */ 496 if (PreviousState) 497 { 498 /* Entry SEH Block for return */ 499 _SEH2_TRY 500 { 501 /* Return previous state */ 502 *PreviousState = Prev; 503 } 504 _SEH2_EXCEPT(ExSystemExceptionFilter()) 505 { 506 Status = _SEH2_GetExceptionCode(); 507 } 508 _SEH2_END; 509 } 510 } 511 512 /* Return Status */ 513 return Status; 514 } 515 516 /* 517 * @implemented 518 */ 519 NTSTATUS 520 NTAPI 521 NtSetEventBoostPriority(IN HANDLE EventHandle) 522 { 523 PKEVENT Event; 524 NTSTATUS Status; 525 PAGED_CODE(); 526 527 /* Open the Object */ 528 Status = ObReferenceObjectByHandle(EventHandle, 529 EVENT_MODIFY_STATE, 530 ExEventObjectType, 531 ExGetPreviousMode(), 532 (PVOID*)&Event, 533 NULL); 534 if (NT_SUCCESS(Status)) 535 { 536 /* Set the Event */ 537 KeSetEventBoostPriority(Event, NULL); 538 ObDereferenceObject(Event); 539 } 540 541 /* Return Status */ 542 return Status; 543 } 544 545 /* EOF */ 546