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