[SHELL32] SHChangeNotify: Use tree for CDirectoryList (#6784)
[reactos.git] / drivers / ksfilter / ks / event.c
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 }