[KS]
[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 #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 PKSEVENT_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 PKSEVENT_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 KSDDKAPI
402 NTSTATUS
403 NTAPI
404 KsEnableEventWithAllocator(
405 IN PIRP Irp,
406 IN ULONG EventSetsCount,
407 IN PKSEVENT_SET EventSet,
408 IN OUT PLIST_ENTRY EventsList OPTIONAL,
409 IN KSEVENTS_LOCKTYPE EventsFlags OPTIONAL,
410 IN PVOID EventsLock OPTIONAL,
411 IN PFNKSALLOCATOR Allocator OPTIONAL,
412 IN ULONG EventItemSize OPTIONAL)
413 {
414 return KspEnableEvent(Irp, EventSetsCount, EventSet, EventsList, EventsFlags, EventsLock, Allocator, EventItemSize);
415 }
416
417 BOOLEAN
418 NTAPI
419 KspDisableEvent(
420 IN PKSEVENT_CTX Ctx)
421 {
422 PIO_STACK_LOCATION IoStack;
423 PKSEVENTDATA EventData;
424 PKSEVENT_ENTRY EventEntry;
425 PLIST_ENTRY Entry;
426
427 if (!Ctx || !Ctx->List || !Ctx->FileObject || !Ctx->Irp)
428 {
429 /* invalid parameter */
430 return FALSE;
431 }
432
433 /* get current irp stack location */
434 IoStack = IoGetCurrentIrpStackLocation(Ctx->Irp);
435
436 /* get event data */
437 EventData = (PKSEVENTDATA)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
438
439 /* point to first entry */
440 Entry = Ctx->List->Flink;
441
442 while(Entry != Ctx->List)
443 {
444 /* get event entry */
445 EventEntry = (PKSEVENT_ENTRY)CONTAINING_RECORD(Entry, KSEVENT_ENTRY, ListEntry);
446
447 if (EventEntry->EventData == EventData && EventEntry->FileObject == Ctx->FileObject)
448 {
449 /* found the entry */
450 RemoveEntryList(&EventEntry->ListEntry);
451 Ctx->EventEntry = EventEntry;
452 return TRUE;
453 }
454
455 /* move to next item */
456 Entry = Entry->Flink;
457 }
458 /* entry not found */
459 return TRUE;
460 }
461
462 /*
463 @implemented
464 */
465 KSDDKAPI
466 NTSTATUS
467 NTAPI
468 KsDisableEvent(
469 IN PIRP Irp,
470 IN OUT PLIST_ENTRY EventsList,
471 IN KSEVENTS_LOCKTYPE EventsFlags,
472 IN PVOID EventsLock)
473 {
474 PIO_STACK_LOCATION IoStack;
475 KSEVENT_CTX Ctx;
476
477 /* get current irp stack location */
478 IoStack = IoGetCurrentIrpStackLocation(Irp);
479
480 /* is there a event entry */
481 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSEVENTDATA))
482 {
483 if (IoStack->Parameters.DeviceIoControl.InputBufferLength == 0)
484 {
485 /* caller wants to free event items */
486 KsFreeEventList(IoStack->FileObject, EventsList, EventsFlags, EventsLock);
487 return STATUS_SUCCESS;
488 }
489 /* invalid parameter */
490 return STATUS_INVALID_BUFFER_SIZE;
491 }
492
493 /* setup event ctx */
494 Ctx.List = EventsList;
495 Ctx.FileObject = IoStack->FileObject;
496 Ctx.Irp = Irp;
497 Ctx.EventEntry = NULL;
498
499 if (KspSynchronizedEventRoutine(EventsFlags, EventsLock, KspDisableEvent, &Ctx))
500 {
501 /* was the event entry found */
502 if (Ctx.EventEntry)
503 {
504 /* discard event */
505 KsDiscardEvent(Ctx.EventEntry);
506 return STATUS_SUCCESS;
507 }
508 /* event was not found */
509 return STATUS_UNSUCCESSFUL;
510 }
511
512 /* invalid parameters */
513 return STATUS_INVALID_PARAMETER;
514 }
515
516 /*
517 @implemented
518 */
519 KSDDKAPI
520 VOID
521 NTAPI
522 KsDiscardEvent(
523 IN PKSEVENT_ENTRY EventEntry)
524 {
525 /* sanity check */
526 ASSERT(EventEntry->Object);
527
528 if (EventEntry->NotificationType == KSEVENTF_SEMAPHORE_HANDLE || EventEntry->NotificationType == KSEVENTF_EVENT_HANDLE)
529 {
530 /* release object */
531 ObDereferenceObject(EventEntry->Object);
532 }
533
534 /* free event entry */
535 FreeItem(EventEntry);
536 }
537
538
539 BOOLEAN
540 NTAPI
541 KspFreeEventList(
542 IN PKSEVENT_CTX Ctx)
543 {
544 PLIST_ENTRY Entry;
545 PKSEVENT_ENTRY EventEntry;
546
547 /* check valid input */
548 if (!Ctx || !Ctx->List)
549 return FALSE;
550
551 if (IsListEmpty(Ctx->List))
552 return FALSE;
553
554 /* remove first entry */
555 Entry = RemoveHeadList(Ctx->List);
556 if (!Entry)
557 {
558 /* list is empty, bye-bye */
559 return FALSE;
560 }
561
562 /* get event entry */
563 EventEntry = (PKSEVENT_ENTRY)CONTAINING_RECORD(Entry, KSEVENT_ENTRY, ListEntry);
564
565 /* store event entry */
566 Ctx->EventEntry = EventEntry;
567 /* return success */
568 return TRUE;
569 }
570
571
572 /*
573 @implemented
574 */
575 KSDDKAPI
576 VOID
577 NTAPI
578 KsFreeEventList(
579 IN PFILE_OBJECT FileObject,
580 IN OUT PLIST_ENTRY EventsList,
581 IN KSEVENTS_LOCKTYPE EventsFlags,
582 IN PVOID EventsLock)
583 {
584 KSEVENT_CTX Ctx;
585
586 /* setup event ctx */
587 Ctx.List = EventsList;
588 Ctx.FileObject = FileObject;
589 Ctx.EventEntry = NULL;
590
591 while(KspSynchronizedEventRoutine(EventsFlags, EventsLock, KspFreeEventList, &Ctx))
592 {
593 if (Ctx.EventEntry)
594 {
595 KsDiscardEvent(Ctx.EventEntry);
596 }
597 }
598 }
599
600
601 /*
602 @implemented
603 */
604 KSDDKAPI
605 NTSTATUS
606 NTAPI
607 KsGenerateEvent(
608 IN PKSEVENT_ENTRY EntryEvent)
609 {
610 if (EntryEvent->NotificationType == KSEVENTF_EVENT_HANDLE || EntryEvent->NotificationType == KSEVENTF_EVENT_OBJECT)
611 {
612 /* signal event */
613 KeSetEvent(EntryEvent->Object, EntryEvent->Reserved, FALSE);
614 }
615 else if (EntryEvent->NotificationType == KSEVENTF_SEMAPHORE_HANDLE || EntryEvent->NotificationType == KSEVENTF_SEMAPHORE_OBJECT)
616 {
617 /* release semaphore */
618 KeReleaseSemaphore(EntryEvent->Object, EntryEvent->Reserved, EntryEvent->SemaphoreAdjustment, FALSE);
619 }
620 else if (EntryEvent->NotificationType == KSEVENTF_DPC)
621 {
622 /* increment reference count to indicate dpc is pending */
623 InterlockedIncrement((PLONG)&EntryEvent->EventData->Dpc.ReferenceCount);
624 /* queue dpc */
625 KeInsertQueueDpc((PRKDPC)EntryEvent->Object, NULL, NULL);
626 }
627 else if (EntryEvent->NotificationType == KSEVENTF_WORKITEM)
628 {
629 /* queue work item */
630 ExQueueWorkItem((PWORK_QUEUE_ITEM)EntryEvent->Object, PtrToUlong(EntryEvent->BufferItem));
631 }
632 else if (EntryEvent->NotificationType == KSEVENTF_KSWORKITEM)
633 {
634 /* queue work item of ks worker */
635 return KsQueueWorkItem((PKSWORKER)EntryEvent->Object, (PWORK_QUEUE_ITEM)EntryEvent->DpcItem);
636 }
637 else
638 {
639 /* unsupported type requested */
640 return STATUS_INVALID_PARAMETER;
641 }
642
643 return STATUS_SUCCESS;
644 }
645
646 /*
647 @unimplemented
648 */
649 KSDDKAPI
650 NTSTATUS
651 NTAPI
652 KsGenerateDataEvent(
653 IN PKSEVENT_ENTRY EventEntry,
654 IN ULONG DataSize,
655 IN PVOID Data)
656 {
657 UNIMPLEMENTED;
658 return STATUS_UNSUCCESSFUL;
659 }
660
661 /*
662 @unimplemented
663 */
664 KSDDKAPI
665 VOID
666 NTAPI
667 KsGenerateEventList(
668 IN GUID* Set OPTIONAL,
669 IN ULONG EventId,
670 IN PLIST_ENTRY EventsList,
671 IN KSEVENTS_LOCKTYPE EventsFlags,
672 IN PVOID EventsLock)
673 {
674 UNIMPLEMENTED
675 }
676
677 /*
678 @implemented
679 */
680 KSDDKAPI
681 VOID
682 NTAPI
683 KsAddEvent(
684 IN PVOID Object,
685 IN PKSEVENT_ENTRY EventEntry)
686 {
687 PKSBASIC_HEADER Header = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
688
689 ExInterlockedInsertTailList(&Header->EventList, &EventEntry->ListEntry, &Header->EventListLock);
690 }
691
692 /*
693 @implemented
694 */
695 NTSTATUS
696 NTAPI
697 KsDefaultAddEventHandler(
698 IN PIRP Irp,
699 IN PKSEVENTDATA EventData,
700 IN OUT PKSEVENT_ENTRY EventEntry)
701 {
702 PIO_STACK_LOCATION IoStack;
703 PKSIOBJECT_HEADER ObjectHeader;
704 PKSBASIC_HEADER Header;
705
706 /* first get the io stack location */
707 IoStack = IoGetCurrentIrpStackLocation(Irp);
708
709 /* now get the object header */
710 ObjectHeader =(PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
711
712 /* sanity check */
713 ASSERT(ObjectHeader->ObjectType);
714
715 /* obtain basic header */
716 Header = (PKSBASIC_HEADER)((ULONG_PTR)ObjectHeader->ObjectType - sizeof(KSBASIC_HEADER));
717
718 /* now insert the event entry */
719 ExInterlockedInsertTailList(&Header->EventList, &EventEntry->ListEntry, &Header->EventListLock);
720
721 /* done */
722 return STATUS_SUCCESS;
723 }
724
725
726
727 /*
728 @unimplemented
729 */
730 KSDDKAPI
731 void
732 NTAPI
733 KsGenerateEvents(
734 IN PVOID Object,
735 IN const GUID* EventSet OPTIONAL,
736 IN ULONG EventId,
737 IN ULONG DataSize,
738 IN PVOID Data OPTIONAL,
739 IN PFNKSGENERATEEVENTCALLBACK CallBack OPTIONAL,
740 IN PVOID CallBackContext OPTIONAL)
741 {
742 UNIMPLEMENTED
743 }