1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Kernel Streaming 4 * FILE: drivers/ksfilter/ks/event.c 5 * PURPOSE: KS Event functions 6 * PROGRAMMER: Johannes Anderwald 7 */ 8 9 #include "precomp.h" 10 11 #define NDEBUG 12 #include <debug.h> 13 14 BOOLEAN 15 KspSynchronizedEventRoutine( 16 IN KSEVENTS_LOCKTYPE EventsFlags, 17 IN PVOID EventsLock, 18 IN PKSEVENT_SYNCHRONIZED_ROUTINE SynchronizedRoutine, 19 IN PKSEVENT_CTX Ctx) 20 { 21 BOOLEAN Result = FALSE; 22 KIRQL OldLevel; 23 24 if (EventsFlags == KSEVENTS_NONE) 25 { 26 /* no synchronization required */ 27 Result = SynchronizedRoutine(Ctx); 28 } 29 else if (EventsFlags == KSEVENTS_SPINLOCK) 30 { 31 /* use spin lock */ 32 KeAcquireSpinLock((PKSPIN_LOCK)EventsLock, &OldLevel); 33 Result = SynchronizedRoutine(Ctx); 34 KeReleaseSpinLock((PKSPIN_LOCK)EventsLock, OldLevel); 35 } 36 else if (EventsFlags == KSEVENTS_MUTEX) 37 { 38 /* use a mutex */ 39 KeWaitForSingleObject(EventsLock, Executive, KernelMode, FALSE, NULL); 40 Result = SynchronizedRoutine(Ctx); 41 KeReleaseMutex((PRKMUTEX)EventsLock, FALSE); 42 } 43 else if (EventsFlags == KSEVENTS_FMUTEX) 44 { 45 /* use a fast mutex */ 46 ExAcquireFastMutex((PFAST_MUTEX)EventsLock); 47 Result = SynchronizedRoutine(Ctx); 48 ExReleaseFastMutex((PFAST_MUTEX)EventsLock); 49 } 50 else if (EventsFlags == KSEVENTS_FMUTEXUNSAFE) 51 { 52 /* acquire fast mutex unsafe */ 53 KeEnterCriticalRegion(); 54 ExAcquireFastMutexUnsafe((PFAST_MUTEX)EventsLock); 55 Result = SynchronizedRoutine(Ctx); 56 ExReleaseFastMutexUnsafe((PFAST_MUTEX)EventsLock); 57 KeLeaveCriticalRegion(); 58 } 59 else if (EventsFlags == KSEVENTS_INTERRUPT) 60 { 61 /* use interrupt for locking */ 62 Result = KeSynchronizeExecution((PKINTERRUPT)EventsLock, (PKSYNCHRONIZE_ROUTINE)SynchronizedRoutine, (PVOID)Ctx); 63 } 64 else if (EventsFlags == KSEVENTS_ERESOURCE) 65 { 66 /* use an eresource */ 67 KeEnterCriticalRegion(); 68 ExAcquireResourceExclusiveLite((PERESOURCE)EventsLock, TRUE); 69 Result = SynchronizedRoutine(Ctx); 70 ExReleaseResourceLite((PERESOURCE)EventsLock); 71 KeLeaveCriticalRegion(); 72 } 73 74 return Result; 75 } 76 77 BOOLEAN 78 NTAPI 79 SyncAddEvent( 80 PKSEVENT_CTX Context) 81 { 82 InsertTailList(Context->List, &Context->EventEntry->ListEntry); 83 return TRUE; 84 } 85 86 NTSTATUS 87 KspEnableEvent( 88 IN PIRP Irp, 89 IN ULONG EventSetsCount, 90 IN const KSEVENT_SET* EventSet, 91 IN OUT PLIST_ENTRY EventsList OPTIONAL, 92 IN KSEVENTS_LOCKTYPE EventsFlags OPTIONAL, 93 IN PVOID EventsLock OPTIONAL, 94 IN PFNKSALLOCATOR Allocator OPTIONAL, 95 IN ULONG EventItemSize OPTIONAL) 96 { 97 PIO_STACK_LOCATION IoStack; 98 NTSTATUS Status; 99 KSEVENT Event; 100 PKSEVENT_ITEM EventItem, FoundEventItem; 101 PKSEVENTDATA EventData; 102 const KSEVENT_SET *FoundEventSet; 103 PKSEVENT_ENTRY EventEntry; 104 ULONG Index, SubIndex, Size; 105 PVOID Object; 106 KSEVENT_CTX Ctx; 107 LPGUID Guid; 108 109 /* get current stack location */ 110 IoStack = IoGetCurrentIrpStackLocation(Irp); 111 112 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSEVENT)) 113 { 114 /* invalid parameter */ 115 return STATUS_NOT_SUPPORTED; 116 } 117 118 if (Irp->RequestorMode == UserMode) 119 { 120 _SEH2_TRY 121 { 122 ProbeForRead(IoStack->Parameters.DeviceIoControl.Type3InputBuffer, sizeof(KSEVENT), sizeof(UCHAR)); 123 ProbeForRead(Irp->UserBuffer, IoStack->Parameters.DeviceIoControl.OutputBufferLength, sizeof(UCHAR)); 124 RtlMoveMemory(&Event, IoStack->Parameters.DeviceIoControl.Type3InputBuffer, sizeof(KSEVENT)); 125 Status = STATUS_SUCCESS; 126 } 127 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 128 { 129 /* Exception, get the error code */ 130 Status = _SEH2_GetExceptionCode(); 131 } 132 _SEH2_END; 133 134 /* check for success */ 135 if (!NT_SUCCESS(Status)) 136 { 137 /* failed to probe parameters */ 138 return Status; 139 } 140 } 141 else 142 { 143 /* copy event struct */ 144 RtlMoveMemory(&Event, IoStack->Parameters.DeviceIoControl.Type3InputBuffer, sizeof(KSEVENT)); 145 } 146 147 FoundEventItem = NULL; 148 FoundEventSet = NULL; 149 150 151 if (IsEqualGUIDAligned(&Event.Set, &GUID_NULL) && Event.Id == 0 && Event.Flags == KSEVENT_TYPE_SETSUPPORT) 152 { 153 // store output size 154 Irp->IoStatus.Information = sizeof(GUID) * EventSetsCount; 155 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(GUID) * EventSetsCount) 156 { 157 // buffer too small 158 return STATUS_MORE_ENTRIES; 159 } 160 161 // get output buffer 162 Guid = (LPGUID)Irp->UserBuffer; 163 164 // copy property guids from property sets 165 for(Index = 0; Index < EventSetsCount; Index++) 166 { 167 RtlMoveMemory(&Guid[Index], EventSet[Index].Set, sizeof(GUID)); 168 } 169 return STATUS_SUCCESS; 170 } 171 172 /* now try to find event set */ 173 for(Index = 0; Index < EventSetsCount; Index++) 174 { 175 if (IsEqualGUIDAligned(&Event.Set, EventSet[Index].Set)) 176 { 177 EventItem = (PKSEVENT_ITEM)EventSet[Index].EventItem; 178 179 /* sanity check */ 180 ASSERT(EventSet[Index].EventsCount); 181 ASSERT(EventItem); 182 183 /* now find matching event id */ 184 for(SubIndex = 0; SubIndex < EventSet[Index].EventsCount; SubIndex++) 185 { 186 if (EventItem[SubIndex].EventId == Event.Id) 187 { 188 /* found event item */ 189 FoundEventItem = &EventItem[SubIndex]; 190 FoundEventSet = &EventSet[Index]; 191 break; 192 } 193 } 194 195 if (FoundEventSet) 196 break; 197 } 198 } 199 200 if (!FoundEventSet) 201 { 202 UNICODE_STRING GuidString; 203 204 RtlStringFromGUID(&Event.Set, &GuidString); 205 206 DPRINT("Guid %S Id %u Flags %x not found\n", GuidString.Buffer, Event.Id, Event.Flags); 207 RtlFreeUnicodeString(&GuidString); 208 return STATUS_PROPSET_NOT_FOUND; 209 210 211 } 212 213 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < FoundEventItem->DataInput) 214 { 215 /* buffer too small */ 216 DPRINT1("Got %u expected %u\n", IoStack->Parameters.DeviceIoControl.OutputBufferLength, FoundEventItem->DataInput); 217 return STATUS_SUCCESS; 218 } 219 220 if (!FoundEventItem->AddHandler && !EventsList) 221 { 222 /* no add handler and no list to add the new entry to */ 223 return STATUS_INVALID_PARAMETER; 224 } 225 226 /* get event data */ 227 EventData = Irp->UserBuffer; 228 229 /* sanity check */ 230 ASSERT(EventData); 231 232 if (Irp->RequestorMode == UserMode) 233 { 234 if (EventData->NotificationType == KSEVENTF_SEMAPHORE_HANDLE) 235 { 236 /* get semaphore object handle */ 237 Status = ObReferenceObjectByHandle(EventData->SemaphoreHandle.Semaphore, SEMAPHORE_MODIFY_STATE, *ExSemaphoreObjectType, Irp->RequestorMode, &Object, NULL); 238 239 if (!NT_SUCCESS(Status)) 240 { 241 /* invalid semaphore handle */ 242 return STATUS_INVALID_PARAMETER; 243 } 244 } 245 else if (EventData->NotificationType == KSEVENTF_EVENT_HANDLE) 246 { 247 /* get event object handle */ 248 Status = ObReferenceObjectByHandle(EventData->EventHandle.Event, EVENT_MODIFY_STATE, *ExEventObjectType, Irp->RequestorMode, &Object, NULL); 249 250 if (!NT_SUCCESS(Status)) 251 { 252 /* invalid event handle */ 253 return STATUS_INVALID_PARAMETER; 254 } 255 } 256 else 257 { 258 /* user mode client can only pass an event or semaphore handle */ 259 return STATUS_INVALID_PARAMETER; 260 } 261 } 262 else 263 { 264 if (EventData->NotificationType != KSEVENTF_EVENT_OBJECT && 265 EventData->NotificationType != KSEVENTF_SEMAPHORE_OBJECT && 266 EventData->NotificationType != KSEVENTF_DPC && 267 EventData->NotificationType != KSEVENTF_WORKITEM && 268 EventData->NotificationType != KSEVENTF_KSWORKITEM) 269 { 270 /* invalid type requested */ 271 return STATUS_INVALID_PARAMETER; 272 } 273 } 274 275 276 /* calculate request size */ 277 Size = sizeof(KSEVENT_ENTRY) + FoundEventItem->ExtraEntryData; 278 279 /* do we have an allocator */ 280 if (Allocator) 281 { 282 /* allocate event entry */ 283 Status = Allocator(Irp, Size, FALSE); 284 285 if (!NT_SUCCESS(Status)) 286 { 287 /* failed */ 288 return Status; 289 } 290 291 /* assume the caller put it there */ 292 EventEntry = KSEVENT_ENTRY_IRP_STORAGE(Irp); 293 294 } 295 else 296 { 297 /* allocate it from nonpaged pool */ 298 EventEntry = AllocateItem(NonPagedPool, Size); 299 } 300 301 if (!EventEntry) 302 { 303 /* not enough memory */ 304 return STATUS_INSUFFICIENT_RESOURCES; 305 } 306 307 /* zero event entry */ 308 RtlZeroMemory(EventEntry, Size); 309 310 /* initialize event entry */ 311 EventEntry->EventData = EventData; 312 EventEntry->NotificationType = EventData->NotificationType; 313 EventEntry->EventItem = FoundEventItem; 314 EventEntry->EventSet = FoundEventSet; 315 EventEntry->FileObject = IoStack->FileObject; 316 317 switch(EventEntry->NotificationType) 318 { 319 case KSEVENTF_EVENT_HANDLE: 320 EventEntry->Object = Object; 321 EventEntry->Reserved = 0; 322 break; 323 case KSEVENTF_SEMAPHORE_HANDLE: 324 EventEntry->Object = Object; 325 EventEntry->SemaphoreAdjustment = EventData->SemaphoreHandle.Adjustment; 326 EventEntry->Reserved = 0; 327 break; 328 case KSEVENTF_EVENT_OBJECT: 329 EventEntry->Object = EventData->EventObject.Event; 330 EventEntry->Reserved = EventData->EventObject.Increment; 331 break; 332 case KSEVENTF_SEMAPHORE_OBJECT: 333 EventEntry->Object = EventData->SemaphoreObject.Semaphore; 334 EventEntry->SemaphoreAdjustment = EventData->SemaphoreObject.Adjustment; 335 EventEntry->Reserved = EventData->SemaphoreObject.Increment; 336 break; 337 case KSEVENTF_DPC: 338 EventEntry->Object = EventData->Dpc.Dpc; 339 EventData->Dpc.ReferenceCount = 0; 340 break; 341 case KSEVENTF_WORKITEM: 342 EventEntry->Object = EventData->WorkItem.WorkQueueItem; 343 EventEntry->BufferItem = (PKSBUFFER_ITEM)UlongToPtr(EventData->WorkItem.WorkQueueType); 344 break; 345 case KSEVENTF_KSWORKITEM: 346 EventEntry->Object = EventData->KsWorkItem.KsWorkerObject; 347 EventEntry->DpcItem = (PKSDPC_ITEM)EventData->KsWorkItem.WorkQueueItem; 348 break; 349 default: 350 /* should not happen */ 351 ASSERT(0); 352 } 353 354 if (FoundEventItem->AddHandler) 355 { 356 /* now add the event */ 357 Status = FoundEventItem->AddHandler(Irp, EventData, EventEntry); 358 359 if (!NT_SUCCESS(Status)) 360 { 361 /* discard event entry */ 362 KsDiscardEvent(EventEntry); 363 } 364 } 365 else 366 { 367 /* setup context */ 368 Ctx.List = EventsList; 369 Ctx.EventEntry = EventEntry; 370 371 /* add the event */ 372 (void)KspSynchronizedEventRoutine(EventsFlags, EventsLock, SyncAddEvent, &Ctx); 373 374 Status = STATUS_SUCCESS; 375 } 376 377 /* done */ 378 return Status; 379 } 380 381 /* 382 @implemented 383 */ 384 KSDDKAPI 385 NTSTATUS 386 NTAPI 387 KsEnableEvent( 388 IN PIRP Irp, 389 IN ULONG EventSetsCount, 390 IN KSEVENT_SET* EventSet, 391 IN OUT PLIST_ENTRY EventsList OPTIONAL, 392 IN KSEVENTS_LOCKTYPE EventsFlags OPTIONAL, 393 IN PVOID EventsLock OPTIONAL) 394 { 395 return KspEnableEvent(Irp, EventSetsCount, EventSet, EventsList, EventsFlags, EventsLock, NULL, 0); 396 } 397 398 /* 399 @implemented 400 */ 401 _IRQL_requires_max_(PASSIVE_LEVEL) 402 KSDDKAPI 403 NTSTATUS 404 NTAPI 405 KsEnableEventWithAllocator( 406 _In_ PIRP Irp, 407 _In_ ULONG EventSetsCount, 408 _In_reads_(EventSetsCount) const KSEVENT_SET* EventSet, 409 _Inout_opt_ PLIST_ENTRY EventsList, 410 _In_opt_ KSEVENTS_LOCKTYPE EventsFlags, 411 _In_opt_ PVOID EventsLock, 412 _In_opt_ PFNKSALLOCATOR Allocator, 413 _In_opt_ ULONG EventItemSize) 414 { 415 return KspEnableEvent(Irp, EventSetsCount, EventSet, EventsList, EventsFlags, EventsLock, Allocator, EventItemSize); 416 } 417 418 BOOLEAN 419 NTAPI 420 KspDisableEvent( 421 IN PKSEVENT_CTX Ctx) 422 { 423 PIO_STACK_LOCATION IoStack; 424 PKSEVENTDATA EventData; 425 PKSEVENT_ENTRY EventEntry; 426 PLIST_ENTRY Entry; 427 428 if (!Ctx || !Ctx->List || !Ctx->FileObject || !Ctx->Irp) 429 { 430 /* invalid parameter */ 431 return FALSE; 432 } 433 434 /* get current irp stack location */ 435 IoStack = IoGetCurrentIrpStackLocation(Ctx->Irp); 436 437 /* get event data */ 438 EventData = (PKSEVENTDATA)IoStack->Parameters.DeviceIoControl.Type3InputBuffer; 439 440 /* point to first entry */ 441 Entry = Ctx->List->Flink; 442 443 while(Entry != Ctx->List) 444 { 445 /* get event entry */ 446 EventEntry = (PKSEVENT_ENTRY)CONTAINING_RECORD(Entry, KSEVENT_ENTRY, ListEntry); 447 448 if (EventEntry->EventData == EventData && EventEntry->FileObject == Ctx->FileObject) 449 { 450 /* found the entry */ 451 RemoveEntryList(&EventEntry->ListEntry); 452 Ctx->EventEntry = EventEntry; 453 return TRUE; 454 } 455 456 /* move to next item */ 457 Entry = Entry->Flink; 458 } 459 /* entry not found */ 460 return TRUE; 461 } 462 463 /* 464 @implemented 465 */ 466 KSDDKAPI 467 NTSTATUS 468 NTAPI 469 KsDisableEvent( 470 IN PIRP Irp, 471 IN OUT PLIST_ENTRY EventsList, 472 IN KSEVENTS_LOCKTYPE EventsFlags, 473 IN PVOID EventsLock) 474 { 475 PIO_STACK_LOCATION IoStack; 476 KSEVENT_CTX Ctx; 477 478 /* get current irp stack location */ 479 IoStack = IoGetCurrentIrpStackLocation(Irp); 480 481 /* is there a event entry */ 482 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSEVENTDATA)) 483 { 484 if (IoStack->Parameters.DeviceIoControl.InputBufferLength == 0) 485 { 486 /* caller wants to free event items */ 487 KsFreeEventList(IoStack->FileObject, EventsList, EventsFlags, EventsLock); 488 return STATUS_SUCCESS; 489 } 490 /* invalid parameter */ 491 return STATUS_INVALID_BUFFER_SIZE; 492 } 493 494 /* setup event ctx */ 495 Ctx.List = EventsList; 496 Ctx.FileObject = IoStack->FileObject; 497 Ctx.Irp = Irp; 498 Ctx.EventEntry = NULL; 499 500 if (KspSynchronizedEventRoutine(EventsFlags, EventsLock, KspDisableEvent, &Ctx)) 501 { 502 /* was the event entry found */ 503 if (Ctx.EventEntry) 504 { 505 /* discard event */ 506 KsDiscardEvent(Ctx.EventEntry); 507 return STATUS_SUCCESS; 508 } 509 /* event was not found */ 510 return STATUS_UNSUCCESSFUL; 511 } 512 513 /* invalid parameters */ 514 return STATUS_INVALID_PARAMETER; 515 } 516 517 /* 518 @implemented 519 */ 520 KSDDKAPI 521 VOID 522 NTAPI 523 KsDiscardEvent( 524 IN PKSEVENT_ENTRY EventEntry) 525 { 526 /* sanity check */ 527 ASSERT(EventEntry->Object); 528 529 if (EventEntry->NotificationType == KSEVENTF_SEMAPHORE_HANDLE || EventEntry->NotificationType == KSEVENTF_EVENT_HANDLE) 530 { 531 /* release object */ 532 ObDereferenceObject(EventEntry->Object); 533 } 534 535 /* free event entry */ 536 FreeItem(EventEntry); 537 } 538 539 540 BOOLEAN 541 NTAPI 542 KspFreeEventList( 543 IN PKSEVENT_CTX Ctx) 544 { 545 PLIST_ENTRY Entry; 546 PKSEVENT_ENTRY EventEntry; 547 548 /* check valid input */ 549 if (!Ctx || !Ctx->List) 550 return FALSE; 551 552 if (IsListEmpty(Ctx->List)) 553 return FALSE; 554 555 /* remove first entry */ 556 Entry = RemoveHeadList(Ctx->List); 557 if (!Entry) 558 { 559 /* list is empty, bye-bye */ 560 return FALSE; 561 } 562 563 /* get event entry */ 564 EventEntry = (PKSEVENT_ENTRY)CONTAINING_RECORD(Entry, KSEVENT_ENTRY, ListEntry); 565 566 /* store event entry */ 567 Ctx->EventEntry = EventEntry; 568 /* return success */ 569 return TRUE; 570 } 571 572 573 /* 574 @implemented 575 */ 576 KSDDKAPI 577 VOID 578 NTAPI 579 KsFreeEventList( 580 IN PFILE_OBJECT FileObject, 581 IN OUT PLIST_ENTRY EventsList, 582 IN KSEVENTS_LOCKTYPE EventsFlags, 583 IN PVOID EventsLock) 584 { 585 KSEVENT_CTX Ctx; 586 587 /* setup event ctx */ 588 Ctx.List = EventsList; 589 Ctx.FileObject = FileObject; 590 Ctx.EventEntry = NULL; 591 592 while(KspSynchronizedEventRoutine(EventsFlags, EventsLock, KspFreeEventList, &Ctx)) 593 { 594 if (Ctx.EventEntry) 595 { 596 KsDiscardEvent(Ctx.EventEntry); 597 } 598 } 599 } 600 601 602 /* 603 @implemented 604 */ 605 KSDDKAPI 606 NTSTATUS 607 NTAPI 608 KsGenerateEvent( 609 IN PKSEVENT_ENTRY EntryEvent) 610 { 611 if (EntryEvent->NotificationType == KSEVENTF_EVENT_HANDLE || EntryEvent->NotificationType == KSEVENTF_EVENT_OBJECT) 612 { 613 /* signal event */ 614 KeSetEvent(EntryEvent->Object, EntryEvent->Reserved, FALSE); 615 } 616 else if (EntryEvent->NotificationType == KSEVENTF_SEMAPHORE_HANDLE || EntryEvent->NotificationType == KSEVENTF_SEMAPHORE_OBJECT) 617 { 618 /* release semaphore */ 619 KeReleaseSemaphore(EntryEvent->Object, EntryEvent->Reserved, EntryEvent->SemaphoreAdjustment, FALSE); 620 } 621 else if (EntryEvent->NotificationType == KSEVENTF_DPC) 622 { 623 /* increment reference count to indicate dpc is pending */ 624 InterlockedIncrement((PLONG)&EntryEvent->EventData->Dpc.ReferenceCount); 625 /* queue dpc */ 626 KeInsertQueueDpc((PRKDPC)EntryEvent->Object, NULL, NULL); 627 } 628 else if (EntryEvent->NotificationType == KSEVENTF_WORKITEM) 629 { 630 /* queue work item */ 631 ExQueueWorkItem((PWORK_QUEUE_ITEM)EntryEvent->Object, PtrToUlong(EntryEvent->BufferItem)); 632 } 633 else if (EntryEvent->NotificationType == KSEVENTF_KSWORKITEM) 634 { 635 /* queue work item of ks worker */ 636 return KsQueueWorkItem((PKSWORKER)EntryEvent->Object, (PWORK_QUEUE_ITEM)EntryEvent->DpcItem); 637 } 638 else 639 { 640 /* unsupported type requested */ 641 return STATUS_INVALID_PARAMETER; 642 } 643 644 return STATUS_SUCCESS; 645 } 646 647 /* 648 @unimplemented 649 */ 650 KSDDKAPI 651 NTSTATUS 652 NTAPI 653 KsGenerateDataEvent( 654 IN PKSEVENT_ENTRY EventEntry, 655 IN ULONG DataSize, 656 IN PVOID Data) 657 { 658 UNIMPLEMENTED; 659 return STATUS_UNSUCCESSFUL; 660 } 661 662 /* 663 @unimplemented 664 */ 665 KSDDKAPI 666 VOID 667 NTAPI 668 KsGenerateEventList( 669 IN GUID* Set OPTIONAL, 670 IN ULONG EventId, 671 IN PLIST_ENTRY EventsList, 672 IN KSEVENTS_LOCKTYPE EventsFlags, 673 IN PVOID EventsLock) 674 { 675 UNIMPLEMENTED; 676 } 677 678 /* 679 @implemented 680 */ 681 KSDDKAPI 682 VOID 683 NTAPI 684 KsAddEvent( 685 IN PVOID Object, 686 IN PKSEVENT_ENTRY EventEntry) 687 { 688 PKSBASIC_HEADER Header = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER)); 689 690 ExInterlockedInsertTailList(&Header->EventList, &EventEntry->ListEntry, &Header->EventListLock); 691 } 692 693 /* 694 @implemented 695 */ 696 NTSTATUS 697 NTAPI 698 KsDefaultAddEventHandler( 699 IN PIRP Irp, 700 IN PKSEVENTDATA EventData, 701 IN OUT PKSEVENT_ENTRY EventEntry) 702 { 703 PIO_STACK_LOCATION IoStack; 704 PKSIOBJECT_HEADER ObjectHeader; 705 PKSBASIC_HEADER Header; 706 707 /* first get the io stack location */ 708 IoStack = IoGetCurrentIrpStackLocation(Irp); 709 710 /* now get the object header */ 711 ObjectHeader =(PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2; 712 713 /* sanity check */ 714 ASSERT(ObjectHeader->ObjectType); 715 716 /* obtain basic header */ 717 Header = (PKSBASIC_HEADER)((ULONG_PTR)ObjectHeader->ObjectType - sizeof(KSBASIC_HEADER)); 718 719 /* now insert the event entry */ 720 ExInterlockedInsertTailList(&Header->EventList, &EventEntry->ListEntry, &Header->EventListLock); 721 722 /* done */ 723 return STATUS_SUCCESS; 724 } 725 726 727 728 /* 729 @unimplemented 730 */ 731 KSDDKAPI 732 void 733 NTAPI 734 KsGenerateEvents( 735 IN PVOID Object, 736 IN const GUID* EventSet OPTIONAL, 737 IN ULONG EventId, 738 IN ULONG DataSize, 739 IN PVOID Data OPTIONAL, 740 IN PFNKSGENERATEEVENTCALLBACK CallBack OPTIONAL, 741 IN PVOID CallBackContext OPTIONAL) 742 { 743 UNIMPLEMENTED; 744 } 745