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 ICI_SQ_SAME( sizeof(EVENT_BASIC_INFORMATION), sizeof(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 EventInformation, 333 EventInformationLength, 334 ReturnLength, 335 NULL, 336 PreviousMode); 337 if(!NT_SUCCESS(Status)) 338 { 339 /* Invalid buffers */ 340 DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status); 341 return Status; 342 } 343 344 /* Get the Object */ 345 Status = ObReferenceObjectByHandle(EventHandle, 346 EVENT_QUERY_STATE, 347 ExEventObjectType, 348 PreviousMode, 349 (PVOID*)&Event, 350 NULL); 351 352 /* Check for success */ 353 if(NT_SUCCESS(Status)) 354 { 355 /* Entry SEH Block */ 356 _SEH2_TRY 357 { 358 /* Return Event Type and State */ 359 BasicInfo->EventType = Event->Header.Type; 360 BasicInfo->EventState = KeReadStateEvent(Event); 361 362 /* Return length */ 363 if(ReturnLength) *ReturnLength = sizeof(EVENT_BASIC_INFORMATION); 364 } 365 _SEH2_EXCEPT(ExSystemExceptionFilter()) 366 { 367 /* Get the exception code */ 368 Status = _SEH2_GetExceptionCode(); 369 } 370 _SEH2_END; 371 372 /* Dereference the Object */ 373 ObDereferenceObject(Event); 374 } 375 376 /* Return status */ 377 return Status; 378 } 379 380 /* 381 * @implemented 382 */ 383 NTSTATUS 384 NTAPI 385 NtResetEvent(IN HANDLE EventHandle, 386 OUT PLONG PreviousState OPTIONAL) 387 { 388 PKEVENT Event; 389 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 390 NTSTATUS Status; 391 PAGED_CODE(); 392 DPRINT("NtResetEvent(EventHandle 0%p PreviousState 0%p)\n", 393 EventHandle, PreviousState); 394 395 /* Check if we were called from user-mode */ 396 if ((PreviousState) && (PreviousMode != KernelMode)) 397 { 398 /* Entry SEH Block */ 399 _SEH2_TRY 400 { 401 /* Make sure the state pointer is valid */ 402 ProbeForWriteLong(PreviousState); 403 } 404 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 405 { 406 /* Return the exception code */ 407 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 408 } 409 _SEH2_END; 410 } 411 412 /* Open the Object */ 413 Status = ObReferenceObjectByHandle(EventHandle, 414 EVENT_MODIFY_STATE, 415 ExEventObjectType, 416 PreviousMode, 417 (PVOID*)&Event, 418 NULL); 419 420 /* Check for success */ 421 if(NT_SUCCESS(Status)) 422 { 423 /* Reset the Event */ 424 LONG Prev = KeResetEvent(Event); 425 ObDereferenceObject(Event); 426 427 /* Check if caller wants the old state back */ 428 if(PreviousState) 429 { 430 /* Entry SEH Block for return */ 431 _SEH2_TRY 432 { 433 /* Return previous state */ 434 *PreviousState = Prev; 435 } 436 _SEH2_EXCEPT(ExSystemExceptionFilter()) 437 { 438 /* Get the exception code */ 439 Status = _SEH2_GetExceptionCode(); 440 } 441 _SEH2_END; 442 } 443 } 444 445 /* Return Status */ 446 return Status; 447 } 448 449 /* 450 * @implemented 451 */ 452 NTSTATUS 453 NTAPI 454 NtSetEvent(IN HANDLE EventHandle, 455 OUT PLONG PreviousState OPTIONAL) 456 { 457 PKEVENT Event; 458 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 459 NTSTATUS Status; 460 PAGED_CODE(); 461 DPRINT("NtSetEvent(EventHandle 0%p PreviousState 0%p)\n", 462 EventHandle, PreviousState); 463 464 /* Check if we were called from user-mode */ 465 if ((PreviousState) && (PreviousMode != KernelMode)) 466 { 467 /* Entry SEH Block */ 468 _SEH2_TRY 469 { 470 /* Make sure the state pointer is valid */ 471 ProbeForWriteLong(PreviousState); 472 } 473 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 474 { 475 /* Return the exception code */ 476 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 477 } 478 _SEH2_END; 479 } 480 481 /* Open the Object */ 482 Status = ObReferenceObjectByHandle(EventHandle, 483 EVENT_MODIFY_STATE, 484 ExEventObjectType, 485 PreviousMode, 486 (PVOID*)&Event, 487 NULL); 488 if (NT_SUCCESS(Status)) 489 { 490 /* Set the Event */ 491 LONG Prev = KeSetEvent(Event, EVENT_INCREMENT, FALSE); 492 ObDereferenceObject(Event); 493 494 /* Check if caller wants the old state back */ 495 if (PreviousState) 496 { 497 /* Entry SEH Block for return */ 498 _SEH2_TRY 499 { 500 /* Return previous state */ 501 *PreviousState = Prev; 502 } 503 _SEH2_EXCEPT(ExSystemExceptionFilter()) 504 { 505 Status = _SEH2_GetExceptionCode(); 506 } 507 _SEH2_END; 508 } 509 } 510 511 /* Return Status */ 512 return Status; 513 } 514 515 /* 516 * @implemented 517 */ 518 NTSTATUS 519 NTAPI 520 NtSetEventBoostPriority(IN HANDLE EventHandle) 521 { 522 PKEVENT Event; 523 NTSTATUS Status; 524 PAGED_CODE(); 525 526 /* Open the Object */ 527 Status = ObReferenceObjectByHandle(EventHandle, 528 EVENT_MODIFY_STATE, 529 ExEventObjectType, 530 ExGetPreviousMode(), 531 (PVOID*)&Event, 532 NULL); 533 if (NT_SUCCESS(Status)) 534 { 535 /* Set the Event */ 536 KeSetEventBoostPriority(Event, NULL); 537 ObDereferenceObject(Event); 538 } 539 540 /* Return Status */ 541 return Status; 542 } 543 544 /* EOF */ 545