2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/ksfilter/ks/filter.c
5 * PURPOSE: KS IKsFilter interface functions
6 * PROGRAMMER: Johannes Anderwald
14 KSBASIC_HEADER Header
;
17 IKsControlVtbl
*lpVtblKsControl
;
18 IKsFilterFactory
* FilterFactory
;
19 IKsProcessingObjectVtbl
* lpVtblKsProcessingObject
;
22 PKSIOBJECT_HEADER ObjectHeader
;
24 PKSFILTERFACTORY Factory
;
25 PFILE_OBJECT FileObject
;
27 KMUTEX ProcessingMutex
;
30 WORK_QUEUE_ITEM WorkItem
;
33 PFNKSFILTERPOWER Sleep
;
34 PFNKSFILTERPOWER Wake
;
36 ULONG
*PinInstanceCount
;
38 PKSPROCESSPIN_INDEXENTRY ProcessPinIndex
;
42 const GUID IID_IKsControl
= {0x28F54685L
, 0x06FD, 0x11D2, {0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
43 const GUID IID_IKsFilter
= {0x3ef6ee44L
, 0x0D41, 0x11d2, {0xbe, 0xDA, 0x00, 0xc0, 0x4f, 0x8e, 0xF4, 0x57}};
44 const GUID KSPROPSETID_Topology
= {0x720D4AC0L
, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
45 const GUID KSPROPSETID_Pin
= {0x8C134960L
, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
48 IKsFilter_RemoveFilterFromFilterFactory(
50 PKSFILTERFACTORY FilterFactory
);
52 NTSTATUS NTAPI
FilterTopologyPropertyHandler(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
53 NTSTATUS NTAPI
FilterPinPropertyHandler(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
56 DEFINE_KSPROPERTY_TOPOLOGYSET(IKsFilterTopologySet
, FilterTopologyPropertyHandler
);
57 DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(IKsFilterPinSet
, FilterPinPropertyHandler
, FilterPinPropertyHandler
, FilterPinPropertyHandler
);
59 KSPROPERTY_SET FilterPropertySet
[] =
62 &KSPROPSETID_Topology
,
63 sizeof(IKsFilterTopologySet
) / sizeof(KSPROPERTY_ITEM
),
64 (const KSPROPERTY_ITEM
*)&IKsFilterTopologySet
,
70 sizeof(IKsFilterPinSet
) / sizeof(KSPROPERTY_ITEM
),
71 (const KSPROPERTY_ITEM
*)&IKsFilterPinSet
,
79 IKsProcessingObject_fnQueryInterface(
80 IKsProcessingObject
* iface
,
84 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsProcessingObject
);
86 if (IsEqualGUIDAligned(refiid
, &IID_IUnknown
))
88 *Output
= &This
->Header
.OuterUnknown
;
89 _InterlockedIncrement(&This
->ref
);
90 return STATUS_SUCCESS
;
92 return STATUS_UNSUCCESSFUL
;
97 IKsProcessingObject_fnAddRef(
98 IKsProcessingObject
* iface
)
100 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsProcessingObject
);
102 return InterlockedIncrement(&This
->ref
);
107 IKsProcessingObject_fnRelease(
108 IKsProcessingObject
* iface
)
110 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsProcessingObject
);
112 InterlockedDecrement(&This
->ref
);
114 /* Return new reference count */
120 IKsProcessingObject_fnProcessingObjectWork(
121 IKsProcessingObject
* iface
)
124 LARGE_INTEGER TimeOut
;
125 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsProcessingObject
);
127 DPRINT1("processing object\n");
128 /* first check if running at passive level */
129 if (KeGetCurrentIrql() == PASSIVE_LEVEL
)
131 /* acquire processing mutex */
132 KeWaitForSingleObject(&This
->ControlMutex
, Executive
, KernelMode
, FALSE
, NULL
);
136 /* dispatch level processing */
137 if (KeReadStateMutex(&This
->ControlMutex
) == 0)
139 /* some thread was faster */
140 DPRINT1("processing object too slow\n");
144 /* acquire processing mutex */
145 TimeOut
.QuadPart
= 0LL;
146 Status
= KeWaitForSingleObject(&This
->ControlMutex
, Executive
, KernelMode
, FALSE
, &TimeOut
);
148 if (Status
== STATUS_TIMEOUT
)
150 /* some thread was faster */
151 DPRINT1("processing object too slow\n");
159 /* check if the and-gate has been enabled again */
160 if (&This
->Gate
.Count
!= 0)
163 DPRINT1("processing object gate open\n");
167 DPRINT1("IKsProcessingObject_fnProcessingObjectWork not implemented\n");
172 /* release process mutex */
173 KeReleaseMutex(&This
->ProcessingMutex
, FALSE
);
178 IKsProcessingObject_fnGetAndGate(
179 IKsProcessingObject
* iface
)
181 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsProcessingObject
);
183 /* return and gate */
189 IKsProcessingObject_fnProcess(
190 IKsProcessingObject
* iface
,
191 IN BOOLEAN Asynchronous
)
193 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsProcessingObject
);
195 /* should the action be asynchronous */
198 /* queue work item */
199 KsQueueWorkItem(This
->Worker
, &This
->WorkItem
);
200 DPRINT1("queueing\n");
205 /* does the filter require explicit deferred processing */
206 if ((This
->Filter
.Descriptor
->Flags
& (KSFILTER_FLAG_DISPATCH_LEVEL_PROCESSING
| KSFILTER_FLAG_CRITICAL_PROCESSING
| KSFILTER_FLAG_HYPERCRITICAL_PROCESSING
)) &&
207 KeGetCurrentIrql() > PASSIVE_LEVEL
)
209 /* queue work item */
210 KsQueueWorkItem(This
->Worker
, &This
->WorkItem
);
211 DPRINT1("queueing\n");
216 /* call worker routine directly */
217 iface
->lpVtbl
->ProcessingObjectWork(iface
);
222 IKsProcessingObject_fnReset(
223 IKsProcessingObject
* iface
)
225 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsProcessingObject
);
227 /* acquire processing mutex */
228 KeWaitForSingleObject(&This
->ProcessingMutex
, Executive
, KernelMode
, FALSE
, NULL
);
230 /* check if the filter supports dispatch routines */
231 if (This
->Filter
.Descriptor
->Dispatch
)
233 /* has the filter a reset routine */
234 if (This
->Filter
.Descriptor
->Dispatch
->Reset
)
237 This
->Filter
.Descriptor
->Dispatch
->Reset(&This
->Filter
);
241 /* release process mutex */
242 KeReleaseMutex(&This
->ProcessingMutex
, FALSE
);
247 IKsProcessingObject_fnTriggerNotification(
248 IKsProcessingObject
* iface
)
253 static IKsProcessingObjectVtbl vt_IKsProcessingObject
=
255 IKsProcessingObject_fnQueryInterface
,
256 IKsProcessingObject_fnAddRef
,
257 IKsProcessingObject_fnRelease
,
258 IKsProcessingObject_fnProcessingObjectWork
,
259 IKsProcessingObject_fnGetAndGate
,
260 IKsProcessingObject_fnProcess
,
261 IKsProcessingObject_fnReset
,
262 IKsProcessingObject_fnTriggerNotification
266 //---------------------------------------------------------------------------------------------------------
269 IKsControl_fnQueryInterface(
274 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsControl
);
276 if (IsEqualGUIDAligned(refiid
, &IID_IUnknown
))
278 *Output
= &This
->Header
.OuterUnknown
;
279 _InterlockedIncrement(&This
->ref
);
280 return STATUS_SUCCESS
;
282 return STATUS_UNSUCCESSFUL
;
290 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsControl
);
292 return InterlockedIncrement(&This
->ref
);
297 IKsControl_fnRelease(
300 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsControl
);
302 InterlockedDecrement(&This
->ref
);
304 /* Return new reference count */
310 IKsControl_fnKsProperty(
312 IN PKSPROPERTY Property
,
313 IN ULONG PropertyLength
,
314 IN OUT PVOID PropertyData
,
316 OUT ULONG
* BytesReturned
)
318 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsControl
);
320 return KsSynchronousIoControlDevice(This
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, Property
, PropertyLength
, PropertyData
, DataLength
, BytesReturned
);
326 IKsControl_fnKsMethod(
329 IN ULONG MethodLength
,
330 IN OUT PVOID MethodData
,
332 OUT ULONG
* BytesReturned
)
334 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsControl
);
336 return KsSynchronousIoControlDevice(This
->FileObject
, KernelMode
, IOCTL_KS_METHOD
, Method
, MethodLength
, MethodData
, DataLength
, BytesReturned
);
342 IKsControl_fnKsEvent(
344 IN PKSEVENT Event OPTIONAL
,
345 IN ULONG EventLength
,
346 IN OUT PVOID EventData
,
348 OUT ULONG
* BytesReturned
)
350 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsControl
);
354 return KsSynchronousIoControlDevice(This
->FileObject
, KernelMode
, IOCTL_KS_ENABLE_EVENT
, Event
, EventLength
, EventData
, DataLength
, BytesReturned
);
358 return KsSynchronousIoControlDevice(This
->FileObject
, KernelMode
, IOCTL_KS_DISABLE_EVENT
, EventData
, DataLength
, NULL
, 0, BytesReturned
);
363 static IKsControlVtbl vt_IKsControl
=
365 IKsControl_fnQueryInterface
,
367 IKsControl_fnRelease
,
368 IKsControl_fnKsProperty
,
369 IKsControl_fnKsMethod
,
376 IKsFilter_fnQueryInterface(
382 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, Header
.OuterUnknown
);
384 if (IsEqualGUIDAligned(refiid
, &IID_IUnknown
) ||
385 IsEqualGUIDAligned(refiid
, &IID_IKsFilter
))
387 *Output
= &This
->Header
.OuterUnknown
;
388 _InterlockedIncrement(&This
->ref
);
389 return STATUS_SUCCESS
;
391 else if (IsEqualGUIDAligned(refiid
, &IID_IKsControl
))
393 *Output
= &This
->lpVtblKsControl
;
394 _InterlockedIncrement(&This
->ref
);
395 return STATUS_SUCCESS
;
398 if (This
->Header
.ClientAggregate
)
400 /* using client aggregate */
401 Status
= This
->Header
.ClientAggregate
->lpVtbl
->QueryInterface(This
->Header
.ClientAggregate
, refiid
, Output
);
403 if (NT_SUCCESS(Status
))
405 /* client aggregate supports interface */
410 DPRINT("IKsFilter_fnQueryInterface no interface\n");
411 return STATUS_NOT_SUPPORTED
;
419 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, Header
.OuterUnknown
);
421 return InterlockedIncrement(&This
->ref
);
429 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, Header
.OuterUnknown
);
431 InterlockedDecrement(&This
->ref
);
438 /* Return new reference count */
445 IKsFilter_fnGetStruct(
448 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, Header
.OuterUnknown
);
450 return &This
->Filter
;
455 IKsFilter_fnDoAllNecessaryPinsExist(
464 IKsFilter_fnCreateNode(
468 IN PLIST_ENTRY ListEntry
)
471 return STATUS_NOT_IMPLEMENTED
;
476 IKsFilter_fnBindProcessPinsToPipeSection(
478 IN
struct KSPROCESSPIPESECTION
*Section
,
482 OUT PKSGATE
*OutGate
)
485 return STATUS_NOT_IMPLEMENTED
;
490 IKsFilter_fnUnbindProcessPinsFromPipeSection(
492 IN
struct KSPROCESSPIPESECTION
*Section
)
495 return STATUS_NOT_IMPLEMENTED
;
500 IKsFilter_fnAddProcessPin(
502 IN PKSPROCESSPIN ProcessPin
)
505 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, Header
.OuterUnknown
);
507 /* first acquire processing mutex */
508 KeWaitForSingleObject(&This
->ProcessingMutex
, Executive
, KernelMode
, FALSE
, NULL
);
511 ASSERT(This
->Filter
.Descriptor
->PinDescriptorsCount
> ProcessPin
->Pin
->Id
);
513 /* allocate new process pin array */
514 Status
= _KsEdit(This
->Filter
.Bag
, (PVOID
*)&This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Pins
,
515 (This
->Filter
.Descriptor
->PinDescriptorsCount
+ 1) * sizeof(PVOID
),
516 This
->Filter
.Descriptor
->PinDescriptorsCount
* sizeof(PVOID
),
519 if (NT_SUCCESS(Status
))
521 /* store process pin */
522 This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Pins
[This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Count
] = ProcessPin
;
523 This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Count
++;
526 /* release process mutex */
527 KeReleaseMutex(&This
->ProcessingMutex
, FALSE
);
534 IKsFilter_fnRemoveProcessPin(
536 IN PKSPROCESSPIN ProcessPin
)
540 PKSPROCESSPIN
* Pins
;
542 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, Header
.OuterUnknown
);
544 /* first acquire processing mutex */
545 KeWaitForSingleObject(&This
->ProcessingMutex
, Executive
, KernelMode
, FALSE
, NULL
);
548 ASSERT(ProcessPin
->Pin
);
549 ASSERT(ProcessPin
->Pin
->Id
);
551 Count
= This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Count
;
552 Pins
= This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Pins
;
554 /* search for current process pin */
555 for(Index
= 0; Index
< Count
; Index
++)
557 if (Pins
[Index
] == ProcessPin
)
559 RtlMoveMemory(&Pins
[Index
], &Pins
[Index
+ 1], (Count
- (Index
+ 1)) * sizeof(PVOID
));
565 /* decrement pin count */
566 This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Count
--;
568 if (!This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Count
)
570 /* clear entry object bag will delete it */
571 This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Pins
= NULL
;
574 /* release process mutex */
575 KeReleaseMutex(&This
->ProcessingMutex
, FALSE
);
578 return STATUS_SUCCESS
;
583 IKsFilter_fnReprepareProcessPipeSection(
585 IN
struct KSPROCESSPIPESECTION
*PipeSection
,
594 IKsFilter_fnDeliverResetState(
596 IN
struct KSPROCESSPIPESECTION
*PipeSection
,
597 IN KSRESET ResetState
)
604 IKsFilter_fnIsFrameHolding(
613 IKsFilter_fnRegisterForCopyCallbacks(
621 PKSPROCESSPIN_INDEXENTRY
623 IKsFilter_fnGetProcessDispatch(
626 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, Header
.OuterUnknown
);
628 return This
->ProcessPinIndex
;
631 static IKsFilterVtbl vt_IKsFilter
=
633 IKsFilter_fnQueryInterface
,
636 IKsFilter_fnGetStruct
,
637 IKsFilter_fnDoAllNecessaryPinsExist
,
638 IKsFilter_fnCreateNode
,
639 IKsFilter_fnBindProcessPinsToPipeSection
,
640 IKsFilter_fnUnbindProcessPinsFromPipeSection
,
641 IKsFilter_fnAddProcessPin
,
642 IKsFilter_fnRemoveProcessPin
,
643 IKsFilter_fnReprepareProcessPipeSection
,
644 IKsFilter_fnDeliverResetState
,
645 IKsFilter_fnIsFrameHolding
,
646 IKsFilter_fnRegisterForCopyCallbacks
,
647 IKsFilter_fnGetProcessDispatch
651 IKsFilter_GetFilterFromIrp(
653 OUT IKsFilter
**Filter
)
655 PIO_STACK_LOCATION IoStack
;
656 PKSIOBJECT_HEADER ObjectHeader
;
659 /* get current irp stack */
660 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
663 ASSERT(IoStack
->FileObject
!= NULL
);
665 ObjectHeader
= (PKSIOBJECT_HEADER
)IoStack
->FileObject
->FsContext2
;
667 /* sanity is important */
668 ASSERT(ObjectHeader
!= NULL
);
669 ASSERT(ObjectHeader
->Type
== KsObjectTypeFilter
);
670 ASSERT(ObjectHeader
->Unknown
!= NULL
);
672 /* get our private interface */
673 Status
= ObjectHeader
->Unknown
->lpVtbl
->QueryInterface(ObjectHeader
->Unknown
, &IID_IKsFilter
, (PVOID
*)Filter
);
675 if (!NT_SUCCESS(Status
))
677 /* something is wrong here */
678 DPRINT1("KS: Misbehaving filter %p\n", ObjectHeader
->Unknown
);
679 Irp
->IoStatus
.Status
= Status
;
681 /* complete and forget irp */
682 CompleteRequest(Irp
, IO_NO_INCREMENT
);
691 IKsFilter_DispatchClose(
692 IN PDEVICE_OBJECT DeviceObject
,
696 IKsFilterImpl
* This
;
699 /* obtain filter from object header */
700 Status
= IKsFilter_GetFilterFromIrp(Irp
, &Filter
);
701 if (!NT_SUCCESS(Status
))
704 /* get our real implementation */
705 This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Header
.OuterUnknown
);
707 /* does the driver support notifications */
708 if (This
->Filter
.Descriptor
&& This
->Filter
.Descriptor
->Dispatch
&& This
->Filter
.Descriptor
->Dispatch
->Close
)
710 /* call driver's filter close function */
711 Status
= This
->Filter
.Descriptor
->Dispatch
->Close(&This
->Filter
, Irp
);
714 if (NT_SUCCESS(Status
) && Status
!= STATUS_PENDING
)
716 /* save the result */
717 Irp
->IoStatus
.Status
= Status
;
719 CompleteRequest(Irp
, IO_NO_INCREMENT
);
721 /* remove our instance from the filter factory */
722 IKsFilter_RemoveFilterFromFilterFactory(This
, This
->Factory
);
724 /* free object header */
725 KsFreeObjectHeader(This
->ObjectHeader
);
729 /* complete and forget */
730 Irp
->IoStatus
.Status
= Status
;
732 CompleteRequest(Irp
, IO_NO_INCREMENT
);
740 KspHandlePropertyInstances(
741 IN PIO_STATUS_BLOCK IoStatus
,
742 IN PKSIDENTIFIER Request
,
744 IN IKsFilterImpl
* This
,
747 KSPIN_CINSTANCES
* Instances
;
748 KSP_PIN
* Pin
= (KSP_PIN
*)Request
;
750 if (!This
->Filter
.Descriptor
|| !This
->Filter
.Descriptor
->PinDescriptorsCount
)
752 /* no filter / pin descriptor */
753 IoStatus
->Status
= STATUS_NOT_IMPLEMENTED
;
754 return STATUS_NOT_IMPLEMENTED
;
757 /* ignore custom structs for now */
758 ASSERT(This
->Filter
.Descriptor
->PinDescriptorSize
== sizeof(KSPIN_DESCRIPTOR_EX
));
759 ASSERT(This
->Filter
.Descriptor
->PinDescriptorsCount
> Pin
->PinId
);
761 Instances
= (KSPIN_CINSTANCES
*)Data
;
762 /* max instance count */
763 Instances
->PossibleCount
= This
->Filter
.Descriptor
->PinDescriptors
[Pin
->PinId
].InstancesPossible
;
764 /* current instance count */
765 Instances
->CurrentCount
= This
->PinInstanceCount
[Pin
->PinId
];
767 IoStatus
->Information
= sizeof(KSPIN_CINSTANCES
);
768 IoStatus
->Status
= STATUS_SUCCESS
;
769 return STATUS_SUCCESS
;
773 KspHandleNecessaryPropertyInstances(
774 IN PIO_STATUS_BLOCK IoStatus
,
775 IN PKSIDENTIFIER Request
,
777 IN IKsFilterImpl
* This
)
780 KSP_PIN
* Pin
= (KSP_PIN
*)Request
;
782 if (!This
->Filter
.Descriptor
|| !This
->Filter
.Descriptor
->PinDescriptorsCount
)
784 /* no filter / pin descriptor */
785 IoStatus
->Status
= STATUS_NOT_IMPLEMENTED
;
786 return STATUS_NOT_IMPLEMENTED
;
789 /* ignore custom structs for now */
790 ASSERT(This
->Filter
.Descriptor
->PinDescriptorSize
== sizeof(KSPIN_DESCRIPTOR_EX
));
791 ASSERT(This
->Filter
.Descriptor
->PinDescriptorsCount
> Pin
->PinId
);
793 Result
= (PULONG
)Data
;
794 *Result
= This
->Filter
.Descriptor
->PinDescriptors
[Pin
->PinId
].InstancesNecessary
;
796 IoStatus
->Information
= sizeof(ULONG
);
797 IoStatus
->Status
= STATUS_SUCCESS
;
798 return STATUS_SUCCESS
;
802 KspHandleDataIntersection(
804 IN PIO_STATUS_BLOCK IoStatus
,
805 IN PKSIDENTIFIER Request
,
808 IN IKsFilterImpl
* This
)
810 PKSMULTIPLE_ITEM MultipleItem
;
811 PKSDATARANGE DataRange
;
812 NTSTATUS Status
= STATUS_NO_MATCH
;
814 PIO_STACK_LOCATION IoStack
;
815 KSP_PIN
* Pin
= (KSP_PIN
*)Request
;
817 /* get stack location */
818 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
821 ASSERT(DataLength
== IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
823 /* Access parameters */
824 MultipleItem
= (PKSMULTIPLE_ITEM
)(Pin
+ 1);
825 DataRange
= (PKSDATARANGE
)(MultipleItem
+ 1);
827 /* FIXME make sure its 64 bit aligned */
828 ASSERT(((ULONG_PTR
)DataRange
& 0x7) == 0);
830 if (!This
->Filter
.Descriptor
|| !This
->Filter
.Descriptor
->PinDescriptorsCount
)
832 /* no filter / pin descriptor */
833 IoStatus
->Status
= STATUS_NOT_IMPLEMENTED
;
834 return STATUS_NOT_IMPLEMENTED
;
837 /* ignore custom structs for now */
838 ASSERT(This
->Filter
.Descriptor
->PinDescriptorSize
== sizeof(KSPIN_DESCRIPTOR_EX
));
839 ASSERT(This
->Filter
.Descriptor
->PinDescriptorsCount
> Pin
->PinId
);
841 if (This
->Filter
.Descriptor
->PinDescriptors
[Pin
->PinId
].IntersectHandler
== NULL
||
842 This
->Filter
.Descriptor
->PinDescriptors
[Pin
->PinId
].PinDescriptor
.DataRanges
== NULL
||
843 This
->Filter
.Descriptor
->PinDescriptors
[Pin
->PinId
].PinDescriptor
.DataRangesCount
== 0)
845 /* no driver supported intersect handler / no provided data ranges */
846 IoStatus
->Status
= STATUS_NOT_IMPLEMENTED
;
847 return STATUS_NOT_IMPLEMENTED
;
850 for(Index
= 0; Index
< MultipleItem
->Count
; Index
++)
852 UNICODE_STRING MajorFormat
, SubFormat
, Specifier
;
853 /* convert the guid to string */
854 RtlStringFromGUID(&DataRange
->MajorFormat
, &MajorFormat
);
855 RtlStringFromGUID(&DataRange
->SubFormat
, &SubFormat
);
856 RtlStringFromGUID(&DataRange
->Specifier
, &Specifier
);
858 DPRINT("KspHandleDataIntersection Index %lu PinId %lu MajorFormat %S SubFormat %S Specifier %S FormatSize %lu SampleSize %lu Align %lu Flags %lx Reserved %lx DataLength %lu\n", Index
, Pin
->PinId
, MajorFormat
.Buffer
, SubFormat
.Buffer
, Specifier
.Buffer
,
859 DataRange
->FormatSize
, DataRange
->SampleSize
, DataRange
->Alignment
, DataRange
->Flags
, DataRange
->Reserved
, DataLength
);
861 /* FIXME implement KsPinDataIntersectionEx */
862 /* Call miniport's properitary handler */
863 Status
= This
->Filter
.Descriptor
->PinDescriptors
[Pin
->PinId
].IntersectHandler(&This
->Filter
,
867 This
->Filter
.Descriptor
->PinDescriptors
[Pin
->PinId
].PinDescriptor
.DataRanges
[0], /* HACK */
871 DPRINT("KspHandleDataIntersection Status %lx\n", Status
);
873 if (Status
== STATUS_SUCCESS
|| Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
876 IoStatus
->Information
= Length
;
880 DataRange
= (PKSDATARANGE
)((PUCHAR
)DataRange
+ DataRange
->FormatSize
);
881 /* FIXME make sure its 64 bit aligned */
882 ASSERT(((ULONG_PTR
)DataRange
& 0x7) == 0);
884 IoStatus
->Status
= Status
;
890 FilterTopologyPropertyHandler(
892 IN PKSIDENTIFIER Request
,
895 IKsFilterImpl
* This
;
897 /* get filter implementation */
898 This
= (IKsFilterImpl
*)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
903 return KsTopologyPropertyHandler(Irp
, Request
, Data
, &This
->Topology
);
910 FilterPinPropertyHandler(
912 IN PKSIDENTIFIER Request
,
915 PIO_STACK_LOCATION IoStack
;
916 IKsFilterImpl
* This
;
917 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
919 /* get filter implementation */
920 This
= (IKsFilterImpl
*)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
925 /* get current stack location */
926 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
930 case KSPROPERTY_PIN_CTYPES
:
931 case KSPROPERTY_PIN_DATAFLOW
:
932 case KSPROPERTY_PIN_DATARANGES
:
933 case KSPROPERTY_PIN_INTERFACES
:
934 case KSPROPERTY_PIN_MEDIUMS
:
935 case KSPROPERTY_PIN_COMMUNICATION
:
936 case KSPROPERTY_PIN_CATEGORY
:
937 case KSPROPERTY_PIN_NAME
:
938 case KSPROPERTY_PIN_CONSTRAINEDDATARANGES
:
939 Status
= KspPinPropertyHandler(Irp
, Request
, Data
, This
->Filter
.Descriptor
->PinDescriptorsCount
, (const KSPIN_DESCRIPTOR
*)This
->Filter
.Descriptor
->PinDescriptors
, This
->Filter
.Descriptor
->PinDescriptorSize
);
941 case KSPROPERTY_PIN_GLOBALCINSTANCES
:
942 Status
= KspHandlePropertyInstances(&Irp
->IoStatus
, Request
, Data
, This
, TRUE
);
944 case KSPROPERTY_PIN_CINSTANCES
:
945 Status
= KspHandlePropertyInstances(&Irp
->IoStatus
, Request
, Data
, This
, FALSE
);
947 case KSPROPERTY_PIN_NECESSARYINSTANCES
:
948 Status
= KspHandleNecessaryPropertyInstances(&Irp
->IoStatus
, Request
, Data
, This
);
951 case KSPROPERTY_PIN_DATAINTERSECTION
:
952 Status
= KspHandleDataIntersection(Irp
, &Irp
->IoStatus
, Request
, Data
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
, This
);
956 Status
= STATUS_NOT_FOUND
;
958 DPRINT("KspPinPropertyHandler Pins %lu Request->Id %lu Status %lx\n", This
->Filter
.Descriptor
->PinDescriptorsCount
, Request
->Id
, Status
);
966 IKsFilter_DispatchDeviceIoControl(
967 IN PDEVICE_OBJECT DeviceObject
,
970 PIO_STACK_LOCATION IoStack
;
972 IKsFilterImpl
* This
;
974 PKSFILTER FilterInstance
;
975 UNICODE_STRING GuidString
;
976 PKSPROPERTY Property
;
979 /* obtain filter from object header */
980 Status
= IKsFilter_GetFilterFromIrp(Irp
, &Filter
);
981 if (!NT_SUCCESS(Status
))
984 /* get our real implementation */
985 This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Header
.OuterUnknown
);
987 /* current irp stack */
988 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
990 /* get property from input buffer */
991 Property
= (PKSPROPERTY
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
993 /* get filter instance */
994 FilterInstance
= Filter
->lpVtbl
->GetStruct(Filter
);
997 ASSERT(IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
>= sizeof(KSIDENTIFIER
));
998 ASSERT(FilterInstance
);
999 ASSERT(FilterInstance
->Descriptor
);
1000 ASSERT(FilterInstance
->Descriptor
->AutomationTable
);
1002 /* acquire control mutex */
1003 KeWaitForSingleObject(This
->Header
.ControlMutex
, Executive
, KernelMode
, FALSE
, NULL
);
1005 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_METHOD
)
1007 const KSMETHOD_SET
*MethodSet
= NULL
;
1008 ULONG MethodItemSize
= 0;
1010 /* check if the driver supports method sets */
1011 if (FilterInstance
->Descriptor
->AutomationTable
->MethodSetsCount
)
1013 SetCount
= FilterInstance
->Descriptor
->AutomationTable
->MethodSetsCount
;
1014 MethodSet
= FilterInstance
->Descriptor
->AutomationTable
->MethodSets
;
1015 MethodItemSize
= FilterInstance
->Descriptor
->AutomationTable
->MethodItemSize
;
1018 /* call method set handler */
1019 Status
= KspMethodHandlerWithAllocator(Irp
, SetCount
, MethodSet
, NULL
, MethodItemSize
);
1021 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_PROPERTY
)
1023 const KSPROPERTY_SET
*PropertySet
= NULL
;
1024 ULONG PropertyItemSize
= 0;
1026 /* check if the driver supports method sets */
1027 if (FilterInstance
->Descriptor
->AutomationTable
->PropertySetsCount
)
1029 SetCount
= FilterInstance
->Descriptor
->AutomationTable
->PropertySetsCount
;
1030 PropertySet
= FilterInstance
->Descriptor
->AutomationTable
->PropertySets
;
1031 PropertyItemSize
= FilterInstance
->Descriptor
->AutomationTable
->PropertyItemSize
;
1032 // FIXME: handle variable sized property items
1033 ASSERT(PropertyItemSize
== sizeof(KSPROPERTY_ITEM
));
1034 PropertyItemSize
= 0;
1037 /* needed for our property handlers */
1038 KSPROPERTY_ITEM_IRP_STORAGE(Irp
) = (KSPROPERTY_ITEM
*)This
;
1040 /* call property handler */
1041 Status
= KspPropertyHandler(Irp
, SetCount
, PropertySet
, NULL
, PropertyItemSize
);
1046 ASSERT(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_ENABLE_EVENT
||
1047 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_DISABLE_EVENT
);
1049 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_ENABLE_EVENT
)
1051 /* call enable event handlers */
1052 Status
= KspEnableEvent(Irp
,
1053 FilterInstance
->Descriptor
->AutomationTable
->EventSetsCount
,
1054 (PKSEVENT_SET
)FilterInstance
->Descriptor
->AutomationTable
->EventSets
,
1055 &This
->Header
.EventList
,
1057 (PVOID
)&This
->Header
.EventListLock
,
1059 FilterInstance
->Descriptor
->AutomationTable
->EventItemSize
);
1063 /* disable event handler */
1064 Status
= KsDisableEvent(Irp
, &This
->Header
.EventList
, KSEVENTS_SPINLOCK
, &This
->Header
.EventListLock
);
1068 RtlStringFromGUID(&Property
->Set
, &GuidString
);
1069 DPRINT("IKsFilter_DispatchDeviceIoControl property PinCount %x\n", FilterInstance
->Descriptor
->PinDescriptorsCount
);
1070 DPRINT("IKsFilter_DispatchDeviceIoControl property Set |%S| Id %u Flags %x Status %lx ResultLength %lu\n", GuidString
.Buffer
, Property
->Id
, Property
->Flags
, Status
, Irp
->IoStatus
.Information
);
1071 RtlFreeUnicodeString(&GuidString
);
1073 /* release filter */
1074 Filter
->lpVtbl
->Release(Filter
);
1076 /* release control mutex */
1077 KeReleaseMutex(This
->Header
.ControlMutex
, FALSE
);
1079 if (Status
!= STATUS_PENDING
)
1081 Irp
->IoStatus
.Status
= Status
;
1082 CompleteRequest(Irp
, IO_NO_INCREMENT
);
1089 static KSDISPATCH_TABLE DispatchTable
=
1091 IKsFilter_DispatchDeviceIoControl
,
1092 KsDispatchInvalidDeviceRequest
,
1093 KsDispatchInvalidDeviceRequest
,
1094 KsDispatchInvalidDeviceRequest
,
1095 IKsFilter_DispatchClose
,
1096 KsDispatchQuerySecurity
,
1097 KsDispatchSetSecurity
,
1098 KsDispatchFastIoDeviceControlFailure
,
1099 KsDispatchFastReadFailure
,
1100 KsDispatchFastReadFailure
,
1105 IKsFilter_CreateDescriptors(
1106 IKsFilterImpl
* This
,
1107 KSFILTER_DESCRIPTOR
* FilterDescriptor
)
1111 PKSNODE_DESCRIPTOR NodeDescriptor
;
1113 /* initialize pin descriptors */
1114 This
->FirstPin
= NULL
;
1115 This
->PinInstanceCount
= NULL
;
1116 This
->ProcessPinIndex
= NULL
;
1118 /* initialize topology descriptor */
1119 This
->Topology
.CategoriesCount
= FilterDescriptor
->CategoriesCount
;
1120 This
->Topology
.Categories
= FilterDescriptor
->Categories
;
1121 This
->Topology
.TopologyNodesCount
= FilterDescriptor
->NodeDescriptorsCount
;
1122 This
->Topology
.TopologyConnectionsCount
= FilterDescriptor
->ConnectionsCount
;
1123 This
->Topology
.TopologyConnections
= FilterDescriptor
->Connections
;
1125 /* are there any templates */
1126 if (FilterDescriptor
->PinDescriptorsCount
)
1129 ASSERT(FilterDescriptor
->PinDescriptors
);
1131 /* FIXME handle variable sized pin descriptors */
1132 ASSERT(FilterDescriptor
->PinDescriptorSize
== sizeof(KSPIN_DESCRIPTOR_EX
));
1134 /* store pin descriptors ex */
1135 Status
= _KsEdit(This
->Filter
.Bag
, (PVOID
*)&This
->Filter
.Descriptor
->PinDescriptors
, FilterDescriptor
->PinDescriptorSize
* FilterDescriptor
->PinDescriptorsCount
,
1136 FilterDescriptor
->PinDescriptorSize
* FilterDescriptor
->PinDescriptorsCount
, 0);
1138 if (!NT_SUCCESS(Status
))
1140 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status
);
1144 /* store pin instance count */
1145 Status
= _KsEdit(This
->Filter
.Bag
, (PVOID
*)&This
->PinInstanceCount
, sizeof(ULONG
) * FilterDescriptor
->PinDescriptorsCount
,
1146 sizeof(ULONG
) * FilterDescriptor
->PinDescriptorsCount
, 0);
1148 if (!NT_SUCCESS(Status
))
1150 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status
);
1154 /* store instantiated pin arrays */
1155 Status
= _KsEdit(This
->Filter
.Bag
, (PVOID
*)&This
->FirstPin
, sizeof(PVOID
) * FilterDescriptor
->PinDescriptorsCount
,
1156 sizeof(PVOID
) * FilterDescriptor
->PinDescriptorsCount
, 0);
1158 if (!NT_SUCCESS(Status
))
1160 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status
);
1164 /* add new pin factory */
1165 RtlMoveMemory((PVOID
)This
->Filter
.Descriptor
->PinDescriptors
, FilterDescriptor
->PinDescriptors
, FilterDescriptor
->PinDescriptorSize
* FilterDescriptor
->PinDescriptorsCount
);
1167 /* allocate process pin index */
1168 Status
= _KsEdit(This
->Filter
.Bag
, (PVOID
*)&This
->ProcessPinIndex
, sizeof(KSPROCESSPIN_INDEXENTRY
) * FilterDescriptor
->PinDescriptorsCount
,
1169 sizeof(KSPROCESSPIN_INDEXENTRY
) * FilterDescriptor
->PinDescriptorsCount
, 0);
1171 if (!NT_SUCCESS(Status
))
1173 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status
);
1180 if (FilterDescriptor
->ConnectionsCount
)
1182 /* modify connections array */
1183 Status
= _KsEdit(This
->Filter
.Bag
,
1184 (PVOID
*)&This
->Filter
.Descriptor
->Connections
,
1185 FilterDescriptor
->ConnectionsCount
* sizeof(KSTOPOLOGY_CONNECTION
),
1186 FilterDescriptor
->ConnectionsCount
* sizeof(KSTOPOLOGY_CONNECTION
),
1189 This
->Topology
.TopologyConnections
= This
->Filter
.Descriptor
->Connections
;
1190 This
->Topology
.TopologyConnectionsCount
= ((PKSFILTER_DESCRIPTOR
)This
->Filter
.Descriptor
)->ConnectionsCount
= FilterDescriptor
->ConnectionsCount
;
1193 if (FilterDescriptor
->NodeDescriptorsCount
)
1196 ASSERT(FilterDescriptor
->NodeDescriptors
);
1199 ASSERT(FilterDescriptor
->NodeDescriptorSize
>= sizeof(KSNODE_DESCRIPTOR
));
1201 This
->Topology
.TopologyNodes
= AllocateItem(NonPagedPool
, sizeof(GUID
) * FilterDescriptor
->NodeDescriptorsCount
);
1202 /* allocate topology node types array */
1203 if (!This
->Topology
.TopologyNodes
)
1205 DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor
->NodeDescriptorsCount
);
1206 return STATUS_INSUFFICIENT_RESOURCES
;
1209 This
->Topology
.TopologyNodesNames
= AllocateItem(NonPagedPool
, sizeof(GUID
) * FilterDescriptor
->NodeDescriptorsCount
);
1210 /* allocate topology names array */
1211 if (!This
->Topology
.TopologyNodesNames
)
1213 FreeItem((PVOID
)This
->Topology
.TopologyNodes
);
1214 DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor
->NodeDescriptorsCount
);
1215 return STATUS_INSUFFICIENT_RESOURCES
;
1218 DPRINT("NodeDescriptorCount %lu\n", FilterDescriptor
->NodeDescriptorsCount
);
1219 NodeDescriptor
= (PKSNODE_DESCRIPTOR
)FilterDescriptor
->NodeDescriptors
;
1220 for(Index
= 0; Index
< FilterDescriptor
->NodeDescriptorsCount
; Index
++)
1222 DPRINT("Index %lu Type %p Name %p\n", Index
, NodeDescriptor
->Type
, NodeDescriptor
->Name
);
1224 /* copy topology type */
1225 if (NodeDescriptor
->Type
)
1226 RtlMoveMemory((PVOID
)&This
->Topology
.TopologyNodes
[Index
], NodeDescriptor
->Type
, sizeof(GUID
));
1228 /* copy topology name */
1229 if (NodeDescriptor
->Name
)
1230 RtlMoveMemory((PVOID
)&This
->Topology
.TopologyNodesNames
[Index
], NodeDescriptor
->Name
, sizeof(GUID
));
1232 // next node descriptor
1233 NodeDescriptor
= (PKSNODE_DESCRIPTOR
)((ULONG_PTR
)NodeDescriptor
+ FilterDescriptor
->NodeDescriptorSize
);
1237 return STATUS_SUCCESS
;
1241 IKsFilter_CopyFilterDescriptor(
1242 IKsFilterImpl
* This
,
1243 const KSFILTER_DESCRIPTOR
* FilterDescriptor
)
1246 KSAUTOMATION_TABLE AutomationTable
;
1248 This
->Filter
.Descriptor
= AllocateItem(NonPagedPool
, sizeof(KSFILTER_DESCRIPTOR
));
1249 if (!This
->Filter
.Descriptor
)
1250 return STATUS_INSUFFICIENT_RESOURCES
;
1252 Status
= KsAddItemToObjectBag(This
->Filter
.Bag
, (PVOID
)This
->Filter
.Descriptor
, NULL
);
1253 if (!NT_SUCCESS(Status
))
1255 FreeItem((PVOID
)This
->Filter
.Descriptor
);
1256 This
->Filter
.Descriptor
= NULL
;
1257 return STATUS_INSUFFICIENT_RESOURCES
;
1260 /* copy filter descriptor fields */
1261 RtlMoveMemory((PVOID
)This
->Filter
.Descriptor
, FilterDescriptor
, sizeof(KSFILTER_DESCRIPTOR
));
1263 /* zero automation table */
1264 RtlZeroMemory(&AutomationTable
, sizeof(KSAUTOMATION_TABLE
));
1266 /* setup filter property sets */
1267 AutomationTable
.PropertyItemSize
= sizeof(KSPROPERTY_ITEM
);
1268 AutomationTable
.PropertySetsCount
= 2;
1269 AutomationTable
.PropertySets
= FilterPropertySet
;
1271 /* merge filter automation table */
1272 Status
= KsMergeAutomationTables((PKSAUTOMATION_TABLE
*)&This
->Filter
.Descriptor
->AutomationTable
, (PKSAUTOMATION_TABLE
)FilterDescriptor
->AutomationTable
, &AutomationTable
, This
->Filter
.Bag
);
1283 PKSPIN NextPin
, CurPin
;
1284 PKSBASIC_HEADER BasicHeader
;
1285 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1288 ASSERT(Pin
->Id
< This
->Filter
.Descriptor
->PinDescriptorsCount
);
1290 if (This
->FirstPin
[Pin
->Id
] == NULL
)
1292 /* welcome first pin */
1293 This
->FirstPin
[Pin
->Id
] = Pin
;
1294 This
->PinInstanceCount
[Pin
->Id
]++;
1299 CurPin
= This
->FirstPin
[Pin
->Id
];
1303 /* get next instantiated pin */
1304 NextPin
= KsPinGetNextSiblingPin(CurPin
);
1310 }while(NextPin
!= NULL
);
1312 /* get basic header */
1313 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)CurPin
- sizeof(KSBASIC_HEADER
));
1316 BasicHeader
->Next
.Pin
= Pin
;
1320 IKsFilter_RemovePin(
1324 PKSPIN NextPin
, CurPin
, LastPin
;
1325 PKSBASIC_HEADER BasicHeader
;
1326 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1329 ASSERT(Pin
->Id
< This
->Filter
.Descriptor
->PinDescriptorsCount
);
1332 CurPin
= This
->FirstPin
[Pin
->Id
];
1337 /* get next instantiated pin */
1338 NextPin
= KsPinGetNextSiblingPin(CurPin
);
1344 /* get basic header of last pin */
1345 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)LastPin
- sizeof(KSBASIC_HEADER
));
1347 BasicHeader
->Next
.Pin
= NextPin
;
1351 /* erase last pin */
1352 This
->FirstPin
[Pin
->Id
] = NextPin
;
1354 /* decrement pin instance count */
1355 This
->PinInstanceCount
[Pin
->Id
]--;
1365 }while(NextPin
!= NULL
);
1374 IKsFilter_DispatchCreatePin(
1375 IN PDEVICE_OBJECT DeviceObject
,
1378 IKsFilterImpl
* This
;
1379 PKSOBJECT_CREATE_ITEM CreateItem
;
1380 PKSPIN_CONNECT Connect
;
1383 DPRINT("IKsFilter_DispatchCreatePin\n");
1385 /* get the create item */
1386 CreateItem
= KSCREATE_ITEM_IRP_STORAGE(Irp
);
1388 /* get the filter object */
1389 This
= (IKsFilterImpl
*)CreateItem
->Context
;
1392 ASSERT(This
->Header
.Type
== KsObjectTypeFilter
);
1394 /* acquire control mutex */
1395 KeWaitForSingleObject(This
->Header
.ControlMutex
, Executive
, KernelMode
, FALSE
, NULL
);
1397 /* now validate the connect request */
1398 Status
= KspValidateConnectRequest(Irp
, This
->Filter
.Descriptor
->PinDescriptorsCount
, (PVOID
)This
->Filter
.Descriptor
->PinDescriptors
, This
->Filter
.Descriptor
->PinDescriptorSize
, &Connect
);
1400 DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest %lx\n", Status
);
1402 if (NT_SUCCESS(Status
))
1405 ASSERT(Connect
->PinId
< This
->Filter
.Descriptor
->PinDescriptorsCount
);
1407 DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest PinId %lu CurrentInstanceCount %lu MaxPossible %lu\n", Connect
->PinId
,
1408 This
->PinInstanceCount
[Connect
->PinId
],
1409 This
->Filter
.Descriptor
->PinDescriptors
[Connect
->PinId
].InstancesPossible
);
1411 if (This
->PinInstanceCount
[Connect
->PinId
] < This
->Filter
.Descriptor
->PinDescriptors
[Connect
->PinId
].InstancesPossible
)
1413 /* create the pin */
1414 Status
= KspCreatePin(DeviceObject
, Irp
, This
->Header
.KsDevice
, This
->FilterFactory
, (IKsFilter
*)&This
->Header
.OuterUnknown
, Connect
, (KSPIN_DESCRIPTOR_EX
*)&This
->Filter
.Descriptor
->PinDescriptors
[Connect
->PinId
]);
1416 DPRINT("IKsFilter_DispatchCreatePin KspCreatePin %lx\n", Status
);
1420 /* maximum instance count reached, bye-bye */
1421 Status
= STATUS_UNSUCCESSFUL
;
1422 DPRINT("IKsFilter_DispatchCreatePin MaxInstance %lu CurInstance %lu %lx\n", This
->Filter
.Descriptor
->PinDescriptors
[Connect
->PinId
].InstancesPossible
, This
->PinInstanceCount
[Connect
->PinId
]);
1426 /* release control mutex */
1427 KeReleaseMutex(This
->Header
.ControlMutex
, FALSE
);
1429 if (Status
!= STATUS_PENDING
)
1431 /* complete request */
1432 Irp
->IoStatus
.Status
= Status
;
1433 CompleteRequest(Irp
, IO_NO_INCREMENT
);
1437 DPRINT("IKsFilter_DispatchCreatePin Result %lx\n", Status
);
1443 IKsFilter_DispatchCreateNode(
1444 IN PDEVICE_OBJECT DeviceObject
,
1448 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
1449 CompleteRequest(Irp
, IO_NO_INCREMENT
);
1450 return STATUS_UNSUCCESSFUL
;
1455 IKsFilter_AttachFilterToFilterFactory(
1456 IKsFilterImpl
* This
,
1457 PKSFILTERFACTORY FilterFactory
)
1459 PKSBASIC_HEADER BasicHeader
;
1463 /* get filter factory basic header */
1464 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)FilterFactory
- sizeof(KSBASIC_HEADER
));
1467 ASSERT(BasicHeader
->Type
== KsObjectTypeFilterFactory
);
1469 if (BasicHeader
->FirstChild
.FilterFactory
== NULL
)
1471 /* welcome first instantiated filter */
1472 BasicHeader
->FirstChild
.Filter
= &This
->Filter
;
1476 /* set to first entry */
1477 Filter
= BasicHeader
->FirstChild
.Filter
;
1481 /* get basic header */
1482 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)Filter
- sizeof(KSBASIC_HEADER
));
1484 ASSERT(BasicHeader
->Type
== KsObjectTypeFilter
);
1486 if (BasicHeader
->Next
.Filter
)
1488 /* iterate to next filter factory */
1489 Filter
= BasicHeader
->Next
.Filter
;
1493 /* found last entry */
1498 /* attach filter factory */
1499 BasicHeader
->Next
.Filter
= &This
->Filter
;
1503 IKsFilter_RemoveFilterFromFilterFactory(
1504 IKsFilterImpl
* This
,
1505 PKSFILTERFACTORY FilterFactory
)
1507 PKSBASIC_HEADER BasicHeader
;
1508 PKSFILTER Filter
, LastFilter
;
1510 /* get filter factory basic header */
1511 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)FilterFactory
- sizeof(KSBASIC_HEADER
));
1514 ASSERT(BasicHeader
->Type
== KsObjectTypeFilterFactory
);
1515 ASSERT(BasicHeader
->FirstChild
.Filter
!= NULL
);
1518 /* set to first entry */
1519 Filter
= BasicHeader
->FirstChild
.Filter
;
1524 if (Filter
== &This
->Filter
)
1528 /* get basic header */
1529 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)LastFilter
- sizeof(KSBASIC_HEADER
));
1530 /* remove filter instance */
1531 BasicHeader
->Next
.Filter
= This
->Header
.Next
.Filter
;
1536 /* remove filter instance */
1537 BasicHeader
->FirstChild
.Filter
= This
->Header
.Next
.Filter
;
1542 /* get basic header */
1543 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)Filter
- sizeof(KSBASIC_HEADER
));
1545 ASSERT(BasicHeader
->Type
== KsObjectTypeFilter
);
1547 LastFilter
= Filter
;
1548 if (BasicHeader
->Next
.Filter
)
1550 /* iterate to next filter factory */
1551 Filter
= BasicHeader
->Next
.Filter
;
1555 /* filter is not in list */
1564 IKsFilter_FilterCentricWorker(
1567 IKsProcessingObject
* Object
= (IKsProcessingObject
*)Ctx
;
1573 Object
->lpVtbl
->ProcessingObjectWork(Object
);
1579 IN PDEVICE_OBJECT DeviceObject
,
1581 IN IKsFilterFactory
*iface
)
1583 IKsFilterImpl
* This
;
1584 IKsDevice
*KsDevice
;
1585 PKSFILTERFACTORY Factory
;
1586 PIO_STACK_LOCATION IoStack
;
1587 PDEVICE_EXTENSION DeviceExtension
;
1589 PKSOBJECT_CREATE_ITEM CreateItem
;
1591 /* get device extension */
1592 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1594 /* get the filter factory */
1595 Factory
= iface
->lpVtbl
->GetStruct(iface
);
1597 if (!Factory
|| !Factory
->FilterDescriptor
)
1599 /* Sorry it just will not work */
1600 return STATUS_UNSUCCESSFUL
;
1603 if (Factory
->FilterDescriptor
->Flags
& KSFILTER_FLAG_DENY_USERMODE_ACCESS
)
1605 if (Irp
->RequestorMode
== UserMode
)
1607 /* filter not accessible from user mode */
1608 DPRINT1("Access denied\n");
1609 return STATUS_UNSUCCESSFUL
;
1613 /* allocate filter instance */
1614 This
= AllocateItem(NonPagedPool
, sizeof(IKsFilterImpl
));
1617 DPRINT1("KspCreateFilter OutOfMemory\n");
1618 return STATUS_INSUFFICIENT_RESOURCES
;
1621 /* initialize object bag */
1622 This
->Filter
.Bag
= AllocateItem(NonPagedPool
, sizeof(KSIOBJECT_BAG
));
1623 if (!This
->Filter
.Bag
)
1627 DPRINT1("KspCreateFilter OutOfMemory\n");
1628 return STATUS_INSUFFICIENT_RESOURCES
;
1630 KsDevice
= (IKsDevice
*)&DeviceExtension
->DeviceHeader
->BasicHeader
.OuterUnknown
;
1631 KsDevice
->lpVtbl
->InitializeObjectBag(KsDevice
, (PKSIOBJECT_BAG
)This
->Filter
.Bag
, NULL
);
1633 /* copy filter descriptor */
1634 Status
= IKsFilter_CopyFilterDescriptor(This
, Factory
->FilterDescriptor
);
1635 if (!NT_SUCCESS(Status
))
1637 /* not enough memory */
1638 FreeItem(This
->Filter
.Bag
);
1640 DPRINT("KspCreateFilter IKsFilter_CopyFilterDescriptor failed %lx\n", Status
);
1641 return STATUS_INSUFFICIENT_RESOURCES
;
1644 /* get current irp stack */
1645 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1647 /* allocate create items */
1648 CreateItem
= AllocateItem(NonPagedPool
, sizeof(KSOBJECT_CREATE_ITEM
) * 2);
1652 FreeItem(This
->Filter
.Bag
);
1654 DPRINT1("KspCreateFilter OutOfMemory\n");
1655 return STATUS_INSUFFICIENT_RESOURCES
;
1658 /* initialize pin create item */
1659 CreateItem
[0].Create
= IKsFilter_DispatchCreatePin
;
1660 CreateItem
[0].Context
= (PVOID
)This
;
1661 CreateItem
[0].Flags
= KSCREATE_ITEM_FREEONSTOP
;
1662 RtlInitUnicodeString(&CreateItem
[0].ObjectClass
, KSSTRING_Pin
);
1663 /* initialize node create item */
1664 CreateItem
[1].Create
= IKsFilter_DispatchCreateNode
;
1665 CreateItem
[1].Context
= (PVOID
)This
;
1666 CreateItem
[1].Flags
= KSCREATE_ITEM_FREEONSTOP
;
1667 RtlInitUnicodeString(&CreateItem
[1].ObjectClass
, KSSTRING_TopologyNode
);
1670 /* initialize filter instance */
1672 This
->Header
.OuterUnknown
= (PUNKNOWN
)&vt_IKsFilter
;
1673 This
->lpVtblKsControl
= &vt_IKsControl
;
1674 This
->lpVtblKsProcessingObject
= &vt_IKsProcessingObject
;
1676 This
->Factory
= Factory
;
1677 This
->FilterFactory
= iface
;
1678 This
->FileObject
= IoStack
->FileObject
;
1679 KeInitializeMutex(&This
->ProcessingMutex
, 0);
1681 /* initialize basic header */
1682 This
->Header
.KsDevice
= &DeviceExtension
->DeviceHeader
->KsDevice
;
1683 This
->Header
.Parent
.KsFilterFactory
= iface
->lpVtbl
->GetStruct(iface
);
1684 This
->Header
.Type
= KsObjectTypeFilter
;
1685 This
->Header
.ControlMutex
= &This
->ControlMutex
;
1686 KeInitializeMutex(This
->Header
.ControlMutex
, 0);
1687 InitializeListHead(&This
->Header
.EventList
);
1688 KeInitializeSpinLock(&This
->Header
.EventListLock
);
1690 /* initialize and gate */
1691 KsGateInitializeAnd(&This
->Gate
, NULL
);
1693 /* FIXME initialize and gate based on pin flags */
1695 /* initialize work item */
1696 ExInitializeWorkItem(&This
->WorkItem
, IKsFilter_FilterCentricWorker
, (PVOID
)This
->lpVtblKsProcessingObject
);
1698 /* allocate counted work item */
1699 Status
= KsRegisterCountedWorker(HyperCriticalWorkQueue
, &This
->WorkItem
, &This
->Worker
);
1700 if (!NT_SUCCESS(Status
))
1702 /* what can go wrong, goes wrong */
1703 DPRINT1("KsRegisterCountedWorker failed with %lx\n", Status
);
1705 FreeItem(CreateItem
);
1709 /* allocate the stream descriptors */
1710 Status
= IKsFilter_CreateDescriptors(This
, (PKSFILTER_DESCRIPTOR
)Factory
->FilterDescriptor
);
1711 if (!NT_SUCCESS(Status
))
1713 /* what can go wrong, goes wrong */
1714 DPRINT1("IKsFilter_CreateDescriptors failed with %lx\n", Status
);
1715 KsUnregisterWorker(This
->Worker
);
1717 FreeItem(CreateItem
);
1723 /* does the filter have a filter dispatch */
1724 if (Factory
->FilterDescriptor
->Dispatch
)
1726 /* does it have a create routine */
1727 if (Factory
->FilterDescriptor
->Dispatch
->Create
)
1729 /* now let driver initialize the filter instance */
1731 ASSERT(This
->Header
.KsDevice
);
1732 ASSERT(This
->Header
.KsDevice
->Started
);
1733 Status
= Factory
->FilterDescriptor
->Dispatch
->Create(&This
->Filter
, Irp
);
1735 if (!NT_SUCCESS(Status
) && Status
!= STATUS_PENDING
)
1737 /* driver failed to initialize */
1738 DPRINT1("Driver: Status %x\n", Status
);
1740 /* free filter instance */
1741 KsUnregisterWorker(This
->Worker
);
1743 FreeItem(CreateItem
);
1749 /* now allocate the object header */
1750 Status
= KsAllocateObjectHeader((PVOID
*)&This
->ObjectHeader
, 2, CreateItem
, Irp
, &DispatchTable
);
1751 if (!NT_SUCCESS(Status
))
1753 /* failed to allocate object header */
1754 DPRINT1("Failed to allocate object header %x\n", Status
);
1759 /* initialize object header extra fields */
1760 This
->ObjectHeader
->Type
= KsObjectTypeFilter
;
1761 This
->ObjectHeader
->Unknown
= (PUNKNOWN
)&This
->Header
.OuterUnknown
;
1762 This
->ObjectHeader
->ObjectType
= (PVOID
)&This
->Filter
;
1764 /* attach filter to filter factory */
1765 IKsFilter_AttachFilterToFilterFactory(This
, This
->Header
.Parent
.KsFilterFactory
);
1767 /* completed initialization */
1768 DPRINT1("KspCreateFilter done %lx KsDevice %p\n", Status
, This
->Header
.KsDevice
);
1778 KsFilterAcquireProcessingMutex(
1779 IN PKSFILTER Filter
)
1781 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1783 KeWaitForSingleObject(&This
->ProcessingMutex
, Executive
, KernelMode
, FALSE
, NULL
);
1792 KsFilterReleaseProcessingMutex(
1793 IN PKSFILTER Filter
)
1795 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1797 KeReleaseMutex(&This
->ProcessingMutex
, FALSE
);
1807 KsFilterAddTopologyConnections (
1808 IN PKSFILTER Filter
,
1809 IN ULONG NewConnectionsCount
,
1810 IN
const KSTOPOLOGY_CONNECTION
*const NewTopologyConnections
)
1814 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1816 DPRINT("KsFilterAddTopologyConnections\n");
1818 ASSERT(This
->Filter
.Descriptor
);
1819 Count
= This
->Filter
.Descriptor
->ConnectionsCount
+ NewConnectionsCount
;
1822 /* modify connections array */
1823 Status
= _KsEdit(This
->Filter
.Bag
,
1824 (PVOID
*)&This
->Filter
.Descriptor
->Connections
,
1825 Count
* sizeof(KSTOPOLOGY_CONNECTION
),
1826 This
->Filter
.Descriptor
->ConnectionsCount
* sizeof(KSTOPOLOGY_CONNECTION
),
1829 if (!NT_SUCCESS(Status
))
1832 DPRINT("KsFilterAddTopologyConnections KsEdit failed with %lx\n", Status
);
1836 /* FIXME verify connections */
1838 /* copy new connections */
1839 RtlMoveMemory((PVOID
)&This
->Filter
.Descriptor
->Connections
[This
->Filter
.Descriptor
->ConnectionsCount
],
1840 NewTopologyConnections
,
1841 NewConnectionsCount
* sizeof(KSTOPOLOGY_CONNECTION
));
1843 /* update topology */
1844 This
->Topology
.TopologyConnectionsCount
+= NewConnectionsCount
;
1845 ((PKSFILTER_DESCRIPTOR
)This
->Filter
.Descriptor
)->ConnectionsCount
+= NewConnectionsCount
;
1846 This
->Topology
.TopologyConnections
= This
->Filter
.Descriptor
->Connections
;
1857 KsFilterAttemptProcessing(
1858 IN PKSFILTER Filter
,
1859 IN BOOLEAN Asynchronous
)
1862 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1865 Gate
= This
->lpVtblKsProcessingObject
->GetAndGate((IKsProcessingObject
*)This
->lpVtblKsProcessingObject
);
1867 if (!KsGateCaptureThreshold(Gate
))
1869 /* filter control gate is closed */
1872 DPRINT1("processing\n");
1873 /* try initiate processing */
1874 This
->lpVtblKsProcessingObject
->Process((IKsProcessingObject
*)This
->lpVtblKsProcessingObject
, Asynchronous
);
1883 KsFilterCreateNode (
1884 IN PKSFILTER Filter
,
1885 IN
const KSNODE_DESCRIPTOR
*const NodeDescriptor
,
1889 return STATUS_NOT_IMPLEMENTED
;
1898 KsFilterCreatePinFactory (
1899 IN PKSFILTER Filter
,
1900 IN
const KSPIN_DESCRIPTOR_EX
*const InPinDescriptor
,
1905 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1907 DPRINT("KsFilterCreatePinFactory\n");
1909 /* calculate new count */
1910 Count
= This
->Filter
.Descriptor
->PinDescriptorsCount
+ 1;
1913 ASSERT(This
->Filter
.Descriptor
->PinDescriptorSize
== sizeof(KSPIN_DESCRIPTOR_EX
));
1915 /* modify pin descriptors ex array */
1916 Status
= _KsEdit(This
->Filter
.Bag
, (PVOID
*)&This
->Filter
.Descriptor
->PinDescriptors
, Count
* This
->Filter
.Descriptor
->PinDescriptorSize
, This
->Filter
.Descriptor
->PinDescriptorsCount
* This
->Filter
.Descriptor
->PinDescriptorSize
, 0);
1917 if (!NT_SUCCESS(Status
))
1920 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status
);
1924 /* modify pin instance count array */
1925 Status
= _KsEdit(This
->Filter
.Bag
,(PVOID
*)&This
->PinInstanceCount
, sizeof(ULONG
) * Count
, sizeof(ULONG
) * This
->Filter
.Descriptor
->PinDescriptorsCount
, 0);
1926 if (!NT_SUCCESS(Status
))
1929 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status
);
1933 /* modify first pin array */
1934 Status
= _KsEdit(This
->Filter
.Bag
,(PVOID
*)&This
->FirstPin
, sizeof(PVOID
) * Count
, sizeof(PVOID
) * This
->Filter
.Descriptor
->PinDescriptorsCount
, 0);
1935 if (!NT_SUCCESS(Status
))
1938 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status
);
1942 /* add new pin factory */
1943 RtlMoveMemory((PVOID
)&This
->Filter
.Descriptor
->PinDescriptors
[This
->Filter
.Descriptor
->PinDescriptorsCount
], InPinDescriptor
, sizeof(KSPIN_DESCRIPTOR_EX
));
1945 /* allocate process pin index */
1946 Status
= _KsEdit(This
->Filter
.Bag
, (PVOID
*)&This
->ProcessPinIndex
, sizeof(KSPROCESSPIN_INDEXENTRY
) * Count
,
1947 sizeof(KSPROCESSPIN_INDEXENTRY
) * This
->Filter
.Descriptor
->PinDescriptorsCount
, 0);
1949 if (!NT_SUCCESS(Status
))
1951 DPRINT("KsFilterCreatePinFactory _KsEdit failed %lx\n", Status
);
1955 /* store new pin id */
1956 *PinID
= This
->Filter
.Descriptor
->PinDescriptorsCount
;
1958 /* increment pin descriptor count */
1959 ((PKSFILTER_DESCRIPTOR
)This
->Filter
.Descriptor
)->PinDescriptorsCount
++;
1962 DPRINT("KsFilterCreatePinFactory done\n");
1963 return STATUS_SUCCESS
;
1974 IN PKSFILTER Filter
)
1976 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1978 /* return and-gate */
1988 KsFilterGetChildPinCount(
1989 IN PKSFILTER Filter
,
1992 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1994 if (PinId
>= This
->Filter
.Descriptor
->PinDescriptorsCount
)
1996 /* index is out of bounds */
1999 /* return pin instance count */
2000 return This
->PinInstanceCount
[PinId
];
2009 KsFilterGetFirstChildPin(
2010 IN PKSFILTER Filter
,
2013 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
2015 if (PinId
>= This
->Filter
.Descriptor
->PinDescriptorsCount
)
2017 /* index is out of bounds */
2021 /* return first pin index */
2022 return This
->FirstPin
[PinId
];
2031 KsFilterRegisterPowerCallbacks(
2032 IN PKSFILTER Filter
,
2033 IN PFNKSFILTERPOWER Sleep OPTIONAL
,
2034 IN PFNKSFILTERPOWER Wake OPTIONAL
)
2036 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
2038 This
->Sleep
= Sleep
;
2051 PIO_STACK_LOCATION IoStack
;
2052 PKSIOBJECT_HEADER ObjectHeader
;
2054 DPRINT("KsGetFilterFromIrp\n");
2056 /* get current irp stack location */
2057 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
2060 ASSERT(IoStack
->FileObject
);
2062 /* get object header */
2063 ObjectHeader
= (PKSIOBJECT_HEADER
)IoStack
->FileObject
->FsContext2
;
2065 if (ObjectHeader
->Type
== KsObjectTypeFilter
)
2067 /* irp is targeted at the filter */
2068 return (PKSFILTER
)ObjectHeader
->ObjectType
;
2070 else if (ObjectHeader
->Type
== KsObjectTypePin
)
2072 /* irp is for a pin */
2073 return KsPinGetParentFilter((PKSPIN
)ObjectHeader
->ObjectType
);
2077 /* irp is unappropiate to retrieve a filter */