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
16 KSBASIC_HEADER Header
;
19 IKsControlVtbl
*lpVtblKsControl
;
20 IKsFilterFactory
* FilterFactory
;
21 IKsProcessingObjectVtbl
* lpVtblKsProcessingObject
;
24 PKSIOBJECT_HEADER ObjectHeader
;
26 PKSFILTERFACTORY Factory
;
27 PFILE_OBJECT FileObject
;
29 KMUTEX ProcessingMutex
;
32 WORK_QUEUE_ITEM WorkItem
;
35 PFNKSFILTERPOWER Sleep
;
36 PFNKSFILTERPOWER Wake
;
38 ULONG
*PinInstanceCount
;
40 PKSPROCESSPIN_INDEXENTRY ProcessPinIndex
;
44 const GUID IID_IKsControl
= {0x28F54685L
, 0x06FD, 0x11D2, {0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
45 const GUID IID_IKsFilter
= {0x3ef6ee44L
, 0x0D41, 0x11d2, {0xbe, 0xDA, 0x00, 0xc0, 0x4f, 0x8e, 0xF4, 0x57}};
46 const GUID KSPROPSETID_Topology
= {0x720D4AC0L
, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
47 const GUID KSPROPSETID_Pin
= {0x8C134960L
, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
50 IKsFilter_RemoveFilterFromFilterFactory(
52 PKSFILTERFACTORY FilterFactory
);
54 NTSTATUS NTAPI
FilterTopologyPropertyHandler(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
55 NTSTATUS NTAPI
FilterPinPropertyHandler(IN PIRP Irp
, IN PKSIDENTIFIER Request
, IN OUT PVOID Data
);
58 DEFINE_KSPROPERTY_TOPOLOGYSET(IKsFilterTopologySet
, FilterTopologyPropertyHandler
);
59 DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(IKsFilterPinSet
, FilterPinPropertyHandler
, FilterPinPropertyHandler
, FilterPinPropertyHandler
);
61 KSPROPERTY_SET FilterPropertySet
[] =
64 &KSPROPSETID_Topology
,
65 sizeof(IKsFilterTopologySet
) / sizeof(KSPROPERTY_ITEM
),
66 (const KSPROPERTY_ITEM
*)&IKsFilterTopologySet
,
72 sizeof(IKsFilterPinSet
) / sizeof(KSPROPERTY_ITEM
),
73 (const KSPROPERTY_ITEM
*)&IKsFilterPinSet
,
81 IKsProcessingObject_fnQueryInterface(
82 IKsProcessingObject
* iface
,
86 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsProcessingObject
);
88 if (IsEqualGUIDAligned(refiid
, &IID_IUnknown
))
90 *Output
= &This
->Header
.OuterUnknown
;
91 _InterlockedIncrement(&This
->ref
);
92 return STATUS_SUCCESS
;
94 return STATUS_UNSUCCESSFUL
;
99 IKsProcessingObject_fnAddRef(
100 IKsProcessingObject
* iface
)
102 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsProcessingObject
);
104 return InterlockedIncrement(&This
->ref
);
109 IKsProcessingObject_fnRelease(
110 IKsProcessingObject
* iface
)
112 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsProcessingObject
);
114 InterlockedDecrement(&This
->ref
);
116 /* Return new reference count */
122 IKsProcessingObject_fnProcessingObjectWork(
123 IKsProcessingObject
* iface
)
126 LARGE_INTEGER TimeOut
;
127 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsProcessingObject
);
129 DPRINT1("processing object\n");
130 /* first check if running at passive level */
131 if (KeGetCurrentIrql() == PASSIVE_LEVEL
)
133 /* acquire processing mutex */
134 KeWaitForSingleObject(&This
->ControlMutex
, Executive
, KernelMode
, FALSE
, NULL
);
138 /* dispatch level processing */
139 if (KeReadStateMutex(&This
->ControlMutex
) == 0)
141 /* some thread was faster */
142 DPRINT1("processing object too slow\n");
146 /* acquire processing mutex */
147 TimeOut
.QuadPart
= 0LL;
148 Status
= KeWaitForSingleObject(&This
->ControlMutex
, Executive
, KernelMode
, FALSE
, &TimeOut
);
150 if (Status
== STATUS_TIMEOUT
)
152 /* some thread was faster */
153 DPRINT1("processing object too slow\n");
161 /* check if the and-gate has been enabled again */
162 if (&This
->Gate
.Count
!= 0)
165 DPRINT1("processing object gate open\n");
169 DPRINT1("IKsProcessingObject_fnProcessingObjectWork not implemented\n");
174 /* release process mutex */
175 KeReleaseMutex(&This
->ProcessingMutex
, FALSE
);
180 IKsProcessingObject_fnGetAndGate(
181 IKsProcessingObject
* iface
)
183 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsProcessingObject
);
185 /* return and gate */
191 IKsProcessingObject_fnProcess(
192 IKsProcessingObject
* iface
,
193 IN BOOLEAN Asynchronous
)
195 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsProcessingObject
);
197 /* should the action be asynchronous */
200 /* queue work item */
201 KsQueueWorkItem(This
->Worker
, &This
->WorkItem
);
202 DPRINT1("queueing\n");
207 /* does the filter require explicit deferred processing */
208 if ((This
->Filter
.Descriptor
->Flags
& (KSFILTER_FLAG_DISPATCH_LEVEL_PROCESSING
| KSFILTER_FLAG_CRITICAL_PROCESSING
| KSFILTER_FLAG_HYPERCRITICAL_PROCESSING
)) &&
209 KeGetCurrentIrql() > PASSIVE_LEVEL
)
211 /* queue work item */
212 KsQueueWorkItem(This
->Worker
, &This
->WorkItem
);
213 DPRINT1("queueing\n");
218 /* call worker routine directly */
219 iface
->lpVtbl
->ProcessingObjectWork(iface
);
224 IKsProcessingObject_fnReset(
225 IKsProcessingObject
* iface
)
227 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsProcessingObject
);
229 /* acquire processing mutex */
230 KeWaitForSingleObject(&This
->ProcessingMutex
, Executive
, KernelMode
, FALSE
, NULL
);
232 /* check if the filter supports dispatch routines */
233 if (This
->Filter
.Descriptor
->Dispatch
)
235 /* has the filter a reset routine */
236 if (This
->Filter
.Descriptor
->Dispatch
->Reset
)
239 This
->Filter
.Descriptor
->Dispatch
->Reset(&This
->Filter
);
243 /* release process mutex */
244 KeReleaseMutex(&This
->ProcessingMutex
, FALSE
);
249 IKsProcessingObject_fnTriggerNotification(
250 IKsProcessingObject
* iface
)
255 static IKsProcessingObjectVtbl vt_IKsProcessingObject
=
257 IKsProcessingObject_fnQueryInterface
,
258 IKsProcessingObject_fnAddRef
,
259 IKsProcessingObject_fnRelease
,
260 IKsProcessingObject_fnProcessingObjectWork
,
261 IKsProcessingObject_fnGetAndGate
,
262 IKsProcessingObject_fnProcess
,
263 IKsProcessingObject_fnReset
,
264 IKsProcessingObject_fnTriggerNotification
268 //---------------------------------------------------------------------------------------------------------
271 IKsControl_fnQueryInterface(
276 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsControl
);
278 if (IsEqualGUIDAligned(refiid
, &IID_IUnknown
))
280 *Output
= &This
->Header
.OuterUnknown
;
281 _InterlockedIncrement(&This
->ref
);
282 return STATUS_SUCCESS
;
284 return STATUS_UNSUCCESSFUL
;
292 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsControl
);
294 return InterlockedIncrement(&This
->ref
);
299 IKsControl_fnRelease(
302 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsControl
);
304 InterlockedDecrement(&This
->ref
);
306 /* Return new reference count */
312 IKsControl_fnKsProperty(
314 IN PKSPROPERTY Property
,
315 IN ULONG PropertyLength
,
316 IN OUT PVOID PropertyData
,
318 OUT ULONG
* BytesReturned
)
320 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsControl
);
322 return KsSynchronousIoControlDevice(This
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, Property
, PropertyLength
, PropertyData
, DataLength
, BytesReturned
);
328 IKsControl_fnKsMethod(
331 IN ULONG MethodLength
,
332 IN OUT PVOID MethodData
,
334 OUT ULONG
* BytesReturned
)
336 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsControl
);
338 return KsSynchronousIoControlDevice(This
->FileObject
, KernelMode
, IOCTL_KS_METHOD
, Method
, MethodLength
, MethodData
, DataLength
, BytesReturned
);
344 IKsControl_fnKsEvent(
346 IN PKSEVENT Event OPTIONAL
,
347 IN ULONG EventLength
,
348 IN OUT PVOID EventData
,
350 OUT ULONG
* BytesReturned
)
352 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsControl
);
356 return KsSynchronousIoControlDevice(This
->FileObject
, KernelMode
, IOCTL_KS_ENABLE_EVENT
, Event
, EventLength
, EventData
, DataLength
, BytesReturned
);
360 return KsSynchronousIoControlDevice(This
->FileObject
, KernelMode
, IOCTL_KS_DISABLE_EVENT
, EventData
, DataLength
, NULL
, 0, BytesReturned
);
365 static IKsControlVtbl vt_IKsControl
=
367 IKsControl_fnQueryInterface
,
369 IKsControl_fnRelease
,
370 IKsControl_fnKsProperty
,
371 IKsControl_fnKsMethod
,
378 IKsFilter_fnQueryInterface(
384 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, Header
.OuterUnknown
);
386 if (IsEqualGUIDAligned(refiid
, &IID_IUnknown
) ||
387 IsEqualGUIDAligned(refiid
, &IID_IKsFilter
))
389 *Output
= &This
->Header
.OuterUnknown
;
390 _InterlockedIncrement(&This
->ref
);
391 return STATUS_SUCCESS
;
393 else if (IsEqualGUIDAligned(refiid
, &IID_IKsControl
))
395 *Output
= &This
->lpVtblKsControl
;
396 _InterlockedIncrement(&This
->ref
);
397 return STATUS_SUCCESS
;
400 if (This
->Header
.ClientAggregate
)
402 /* using client aggregate */
403 Status
= This
->Header
.ClientAggregate
->lpVtbl
->QueryInterface(This
->Header
.ClientAggregate
, refiid
, Output
);
405 if (NT_SUCCESS(Status
))
407 /* client aggregate supports interface */
412 DPRINT("IKsFilter_fnQueryInterface no interface\n");
413 return STATUS_NOT_SUPPORTED
;
421 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, Header
.OuterUnknown
);
423 return InterlockedIncrement(&This
->ref
);
431 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, Header
.OuterUnknown
);
433 InterlockedDecrement(&This
->ref
);
440 /* Return new reference count */
447 IKsFilter_fnGetStruct(
450 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, Header
.OuterUnknown
);
452 return &This
->Filter
;
457 IKsFilter_fnDoAllNecessaryPinsExist(
466 IKsFilter_fnCreateNode(
470 IN PLIST_ENTRY ListEntry
)
473 return STATUS_NOT_IMPLEMENTED
;
478 IKsFilter_fnBindProcessPinsToPipeSection(
480 IN
struct KSPROCESSPIPESECTION
*Section
,
484 OUT PKSGATE
*OutGate
)
487 return STATUS_NOT_IMPLEMENTED
;
492 IKsFilter_fnUnbindProcessPinsFromPipeSection(
494 IN
struct KSPROCESSPIPESECTION
*Section
)
497 return STATUS_NOT_IMPLEMENTED
;
502 IKsFilter_fnAddProcessPin(
504 IN PKSPROCESSPIN ProcessPin
)
507 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, Header
.OuterUnknown
);
509 /* first acquire processing mutex */
510 KeWaitForSingleObject(&This
->ProcessingMutex
, Executive
, KernelMode
, FALSE
, NULL
);
513 ASSERT(This
->Filter
.Descriptor
->PinDescriptorsCount
> ProcessPin
->Pin
->Id
);
515 /* allocate new process pin array */
516 Status
= _KsEdit(This
->Filter
.Bag
, (PVOID
*)&This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Pins
,
517 (This
->Filter
.Descriptor
->PinDescriptorsCount
+ 1) * sizeof(PVOID
),
518 This
->Filter
.Descriptor
->PinDescriptorsCount
* sizeof(PVOID
),
521 if (NT_SUCCESS(Status
))
523 /* store process pin */
524 This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Pins
[This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Count
] = ProcessPin
;
525 This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Count
++;
528 /* release process mutex */
529 KeReleaseMutex(&This
->ProcessingMutex
, FALSE
);
536 IKsFilter_fnRemoveProcessPin(
538 IN PKSPROCESSPIN ProcessPin
)
542 PKSPROCESSPIN
* Pins
;
544 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, Header
.OuterUnknown
);
546 /* first acquire processing mutex */
547 KeWaitForSingleObject(&This
->ProcessingMutex
, Executive
, KernelMode
, FALSE
, NULL
);
550 ASSERT(ProcessPin
->Pin
);
551 ASSERT(ProcessPin
->Pin
->Id
);
553 Count
= This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Count
;
554 Pins
= This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Pins
;
556 /* search for current process pin */
557 for(Index
= 0; Index
< Count
; Index
++)
559 if (Pins
[Index
] == ProcessPin
)
561 RtlMoveMemory(&Pins
[Index
], &Pins
[Index
+ 1], (Count
- (Index
+ 1)) * sizeof(PVOID
));
567 /* decrement pin count */
568 This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Count
--;
570 if (!This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Count
)
572 /* clear entry object bag will delete it */
573 This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Pins
= NULL
;
576 /* release process mutex */
577 KeReleaseMutex(&This
->ProcessingMutex
, FALSE
);
580 return STATUS_SUCCESS
;
585 IKsFilter_fnReprepareProcessPipeSection(
587 IN
struct KSPROCESSPIPESECTION
*PipeSection
,
596 IKsFilter_fnDeliverResetState(
598 IN
struct KSPROCESSPIPESECTION
*PipeSection
,
599 IN KSRESET ResetState
)
606 IKsFilter_fnIsFrameHolding(
615 IKsFilter_fnRegisterForCopyCallbacks(
623 PKSPROCESSPIN_INDEXENTRY
625 IKsFilter_fnGetProcessDispatch(
628 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, Header
.OuterUnknown
);
630 return This
->ProcessPinIndex
;
633 static IKsFilterVtbl vt_IKsFilter
=
635 IKsFilter_fnQueryInterface
,
638 IKsFilter_fnGetStruct
,
639 IKsFilter_fnDoAllNecessaryPinsExist
,
640 IKsFilter_fnCreateNode
,
641 IKsFilter_fnBindProcessPinsToPipeSection
,
642 IKsFilter_fnUnbindProcessPinsFromPipeSection
,
643 IKsFilter_fnAddProcessPin
,
644 IKsFilter_fnRemoveProcessPin
,
645 IKsFilter_fnReprepareProcessPipeSection
,
646 IKsFilter_fnDeliverResetState
,
647 IKsFilter_fnIsFrameHolding
,
648 IKsFilter_fnRegisterForCopyCallbacks
,
649 IKsFilter_fnGetProcessDispatch
653 IKsFilter_GetFilterFromIrp(
655 OUT IKsFilter
**Filter
)
657 PIO_STACK_LOCATION IoStack
;
658 PKSIOBJECT_HEADER ObjectHeader
;
661 /* get current irp stack */
662 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
665 ASSERT(IoStack
->FileObject
!= NULL
);
667 ObjectHeader
= (PKSIOBJECT_HEADER
)IoStack
->FileObject
->FsContext2
;
669 /* sanity is important */
670 ASSERT(ObjectHeader
!= NULL
);
671 ASSERT(ObjectHeader
->Type
== KsObjectTypeFilter
);
672 ASSERT(ObjectHeader
->Unknown
!= NULL
);
674 /* get our private interface */
675 Status
= ObjectHeader
->Unknown
->lpVtbl
->QueryInterface(ObjectHeader
->Unknown
, &IID_IKsFilter
, (PVOID
*)Filter
);
677 if (!NT_SUCCESS(Status
))
679 /* something is wrong here */
680 DPRINT1("KS: Misbehaving filter %p\n", ObjectHeader
->Unknown
);
681 Irp
->IoStatus
.Status
= Status
;
683 /* complete and forget irp */
684 CompleteRequest(Irp
, IO_NO_INCREMENT
);
693 IKsFilter_DispatchClose(
694 IN PDEVICE_OBJECT DeviceObject
,
698 IKsFilterImpl
* This
;
701 /* obtain filter from object header */
702 Status
= IKsFilter_GetFilterFromIrp(Irp
, &Filter
);
703 if (!NT_SUCCESS(Status
))
706 /* get our real implementation */
707 This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Header
.OuterUnknown
);
709 /* does the driver support notifications */
710 if (This
->Filter
.Descriptor
&& This
->Filter
.Descriptor
->Dispatch
&& This
->Filter
.Descriptor
->Dispatch
->Close
)
712 /* call driver's filter close function */
713 Status
= This
->Filter
.Descriptor
->Dispatch
->Close(&This
->Filter
, Irp
);
716 if (NT_SUCCESS(Status
) && Status
!= STATUS_PENDING
)
718 /* save the result */
719 Irp
->IoStatus
.Status
= Status
;
721 CompleteRequest(Irp
, IO_NO_INCREMENT
);
723 /* remove our instance from the filter factory */
724 IKsFilter_RemoveFilterFromFilterFactory(This
, This
->Factory
);
726 /* free object header */
727 KsFreeObjectHeader(This
->ObjectHeader
);
731 /* complete and forget */
732 Irp
->IoStatus
.Status
= Status
;
734 CompleteRequest(Irp
, IO_NO_INCREMENT
);
742 KspHandlePropertyInstances(
743 IN PIO_STATUS_BLOCK IoStatus
,
744 IN PKSIDENTIFIER Request
,
746 IN IKsFilterImpl
* This
,
749 KSPIN_CINSTANCES
* Instances
;
750 KSP_PIN
* Pin
= (KSP_PIN
*)Request
;
752 if (!This
->Filter
.Descriptor
|| !This
->Filter
.Descriptor
->PinDescriptorsCount
)
754 /* no filter / pin descriptor */
755 IoStatus
->Status
= STATUS_NOT_IMPLEMENTED
;
756 return STATUS_NOT_IMPLEMENTED
;
759 /* ignore custom structs for now */
760 ASSERT(This
->Filter
.Descriptor
->PinDescriptorSize
== sizeof(KSPIN_DESCRIPTOR_EX
));
761 ASSERT(This
->Filter
.Descriptor
->PinDescriptorsCount
> Pin
->PinId
);
763 Instances
= (KSPIN_CINSTANCES
*)Data
;
764 /* max instance count */
765 Instances
->PossibleCount
= This
->Filter
.Descriptor
->PinDescriptors
[Pin
->PinId
].InstancesPossible
;
766 /* current instance count */
767 Instances
->CurrentCount
= This
->PinInstanceCount
[Pin
->PinId
];
769 IoStatus
->Information
= sizeof(KSPIN_CINSTANCES
);
770 IoStatus
->Status
= STATUS_SUCCESS
;
771 return STATUS_SUCCESS
;
775 KspHandleNecessaryPropertyInstances(
776 IN PIO_STATUS_BLOCK IoStatus
,
777 IN PKSIDENTIFIER Request
,
779 IN IKsFilterImpl
* This
)
782 KSP_PIN
* Pin
= (KSP_PIN
*)Request
;
784 if (!This
->Filter
.Descriptor
|| !This
->Filter
.Descriptor
->PinDescriptorsCount
)
786 /* no filter / pin descriptor */
787 IoStatus
->Status
= STATUS_NOT_IMPLEMENTED
;
788 return STATUS_NOT_IMPLEMENTED
;
791 /* ignore custom structs for now */
792 ASSERT(This
->Filter
.Descriptor
->PinDescriptorSize
== sizeof(KSPIN_DESCRIPTOR_EX
));
793 ASSERT(This
->Filter
.Descriptor
->PinDescriptorsCount
> Pin
->PinId
);
795 Result
= (PULONG
)Data
;
796 *Result
= This
->Filter
.Descriptor
->PinDescriptors
[Pin
->PinId
].InstancesNecessary
;
798 IoStatus
->Information
= sizeof(ULONG
);
799 IoStatus
->Status
= STATUS_SUCCESS
;
800 return STATUS_SUCCESS
;
804 KspHandleDataIntersection(
806 IN PIO_STATUS_BLOCK IoStatus
,
807 IN PKSIDENTIFIER Request
,
810 IN IKsFilterImpl
* This
)
812 PKSMULTIPLE_ITEM MultipleItem
;
813 PKSDATARANGE DataRange
;
814 NTSTATUS Status
= STATUS_NO_MATCH
;
816 PIO_STACK_LOCATION IoStack
;
817 KSP_PIN
* Pin
= (KSP_PIN
*)Request
;
819 /* get stack location */
820 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
823 ASSERT(DataLength
== IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
825 /* Access parameters */
826 MultipleItem
= (PKSMULTIPLE_ITEM
)(Pin
+ 1);
827 DataRange
= (PKSDATARANGE
)(MultipleItem
+ 1);
829 /* FIXME make sure its 64 bit aligned */
830 ASSERT(((ULONG_PTR
)DataRange
& 0x7) == 0);
832 if (!This
->Filter
.Descriptor
|| !This
->Filter
.Descriptor
->PinDescriptorsCount
)
834 /* no filter / pin descriptor */
835 IoStatus
->Status
= STATUS_NOT_IMPLEMENTED
;
836 return STATUS_NOT_IMPLEMENTED
;
839 /* ignore custom structs for now */
840 ASSERT(This
->Filter
.Descriptor
->PinDescriptorSize
== sizeof(KSPIN_DESCRIPTOR_EX
));
841 ASSERT(This
->Filter
.Descriptor
->PinDescriptorsCount
> Pin
->PinId
);
843 if (This
->Filter
.Descriptor
->PinDescriptors
[Pin
->PinId
].IntersectHandler
== NULL
||
844 This
->Filter
.Descriptor
->PinDescriptors
[Pin
->PinId
].PinDescriptor
.DataRanges
== NULL
||
845 This
->Filter
.Descriptor
->PinDescriptors
[Pin
->PinId
].PinDescriptor
.DataRangesCount
== 0)
847 /* no driver supported intersect handler / no provided data ranges */
848 IoStatus
->Status
= STATUS_NOT_IMPLEMENTED
;
849 return STATUS_NOT_IMPLEMENTED
;
852 for(Index
= 0; Index
< MultipleItem
->Count
; Index
++)
854 UNICODE_STRING MajorFormat
, SubFormat
, Specifier
;
855 /* convert the guid to string */
856 RtlStringFromGUID(&DataRange
->MajorFormat
, &MajorFormat
);
857 RtlStringFromGUID(&DataRange
->SubFormat
, &SubFormat
);
858 RtlStringFromGUID(&DataRange
->Specifier
, &Specifier
);
860 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
,
861 DataRange
->FormatSize
, DataRange
->SampleSize
, DataRange
->Alignment
, DataRange
->Flags
, DataRange
->Reserved
, DataLength
);
863 /* FIXME implement KsPinDataIntersectionEx */
864 /* Call miniport's properitary handler */
865 Status
= This
->Filter
.Descriptor
->PinDescriptors
[Pin
->PinId
].IntersectHandler(&This
->Filter
,
869 This
->Filter
.Descriptor
->PinDescriptors
[Pin
->PinId
].PinDescriptor
.DataRanges
[0], /* HACK */
873 DPRINT("KspHandleDataIntersection Status %lx\n", Status
);
875 if (Status
== STATUS_SUCCESS
|| Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
878 IoStatus
->Information
= Length
;
882 DataRange
= (PKSDATARANGE
)((PUCHAR
)DataRange
+ DataRange
->FormatSize
);
883 /* FIXME make sure its 64 bit aligned */
884 ASSERT(((ULONG_PTR
)DataRange
& 0x7) == 0);
886 IoStatus
->Status
= Status
;
892 FilterTopologyPropertyHandler(
894 IN PKSIDENTIFIER Request
,
897 IKsFilterImpl
* This
;
899 /* get filter implementation */
900 This
= (IKsFilterImpl
*)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
905 return KsTopologyPropertyHandler(Irp
, Request
, Data
, &This
->Topology
);
912 FilterPinPropertyHandler(
914 IN PKSIDENTIFIER Request
,
917 PIO_STACK_LOCATION IoStack
;
918 IKsFilterImpl
* This
;
919 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
921 /* get filter implementation */
922 This
= (IKsFilterImpl
*)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
927 /* get current stack location */
928 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
932 case KSPROPERTY_PIN_CTYPES
:
933 case KSPROPERTY_PIN_DATAFLOW
:
934 case KSPROPERTY_PIN_DATARANGES
:
935 case KSPROPERTY_PIN_INTERFACES
:
936 case KSPROPERTY_PIN_MEDIUMS
:
937 case KSPROPERTY_PIN_COMMUNICATION
:
938 case KSPROPERTY_PIN_CATEGORY
:
939 case KSPROPERTY_PIN_NAME
:
940 case KSPROPERTY_PIN_CONSTRAINEDDATARANGES
:
941 Status
= KspPinPropertyHandler(Irp
, Request
, Data
, This
->Filter
.Descriptor
->PinDescriptorsCount
, (const KSPIN_DESCRIPTOR
*)This
->Filter
.Descriptor
->PinDescriptors
, This
->Filter
.Descriptor
->PinDescriptorSize
);
943 case KSPROPERTY_PIN_GLOBALCINSTANCES
:
944 Status
= KspHandlePropertyInstances(&Irp
->IoStatus
, Request
, Data
, This
, TRUE
);
946 case KSPROPERTY_PIN_CINSTANCES
:
947 Status
= KspHandlePropertyInstances(&Irp
->IoStatus
, Request
, Data
, This
, FALSE
);
949 case KSPROPERTY_PIN_NECESSARYINSTANCES
:
950 Status
= KspHandleNecessaryPropertyInstances(&Irp
->IoStatus
, Request
, Data
, This
);
953 case KSPROPERTY_PIN_DATAINTERSECTION
:
954 Status
= KspHandleDataIntersection(Irp
, &Irp
->IoStatus
, Request
, Data
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
, This
);
958 Status
= STATUS_NOT_FOUND
;
960 DPRINT("KspPinPropertyHandler Pins %lu Request->Id %lu Status %lx\n", This
->Filter
.Descriptor
->PinDescriptorsCount
, Request
->Id
, Status
);
968 IKsFilter_DispatchDeviceIoControl(
969 IN PDEVICE_OBJECT DeviceObject
,
972 PIO_STACK_LOCATION IoStack
;
974 IKsFilterImpl
* This
;
976 PKSFILTER FilterInstance
;
977 UNICODE_STRING GuidString
;
978 PKSPROPERTY Property
;
981 /* obtain filter from object header */
982 Status
= IKsFilter_GetFilterFromIrp(Irp
, &Filter
);
983 if (!NT_SUCCESS(Status
))
986 /* get our real implementation */
987 This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Header
.OuterUnknown
);
989 /* current irp stack */
990 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
992 /* get property from input buffer */
993 Property
= (PKSPROPERTY
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
995 /* get filter instance */
996 FilterInstance
= Filter
->lpVtbl
->GetStruct(Filter
);
999 ASSERT(IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
>= sizeof(KSIDENTIFIER
));
1000 ASSERT(FilterInstance
);
1001 ASSERT(FilterInstance
->Descriptor
);
1002 ASSERT(FilterInstance
->Descriptor
->AutomationTable
);
1004 /* acquire control mutex */
1005 KeWaitForSingleObject(This
->Header
.ControlMutex
, Executive
, KernelMode
, FALSE
, NULL
);
1007 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_METHOD
)
1009 const KSMETHOD_SET
*MethodSet
= NULL
;
1010 ULONG MethodItemSize
= 0;
1012 /* check if the driver supports method sets */
1013 if (FilterInstance
->Descriptor
->AutomationTable
->MethodSetsCount
)
1015 SetCount
= FilterInstance
->Descriptor
->AutomationTable
->MethodSetsCount
;
1016 MethodSet
= FilterInstance
->Descriptor
->AutomationTable
->MethodSets
;
1017 MethodItemSize
= FilterInstance
->Descriptor
->AutomationTable
->MethodItemSize
;
1020 /* call method set handler */
1021 Status
= KspMethodHandlerWithAllocator(Irp
, SetCount
, MethodSet
, NULL
, MethodItemSize
);
1023 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_PROPERTY
)
1025 const KSPROPERTY_SET
*PropertySet
= NULL
;
1026 ULONG PropertyItemSize
= 0;
1028 /* check if the driver supports method sets */
1029 if (FilterInstance
->Descriptor
->AutomationTable
->PropertySetsCount
)
1031 SetCount
= FilterInstance
->Descriptor
->AutomationTable
->PropertySetsCount
;
1032 PropertySet
= FilterInstance
->Descriptor
->AutomationTable
->PropertySets
;
1033 PropertyItemSize
= FilterInstance
->Descriptor
->AutomationTable
->PropertyItemSize
;
1034 // FIXME: handle variable sized property items
1035 ASSERT(PropertyItemSize
== sizeof(KSPROPERTY_ITEM
));
1036 PropertyItemSize
= 0;
1039 /* needed for our property handlers */
1040 KSPROPERTY_ITEM_IRP_STORAGE(Irp
) = (KSPROPERTY_ITEM
*)This
;
1042 /* call property handler */
1043 Status
= KspPropertyHandler(Irp
, SetCount
, PropertySet
, NULL
, PropertyItemSize
);
1048 ASSERT(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_ENABLE_EVENT
||
1049 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_DISABLE_EVENT
);
1051 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_ENABLE_EVENT
)
1053 /* call enable event handlers */
1054 Status
= KspEnableEvent(Irp
,
1055 FilterInstance
->Descriptor
->AutomationTable
->EventSetsCount
,
1056 (PKSEVENT_SET
)FilterInstance
->Descriptor
->AutomationTable
->EventSets
,
1057 &This
->Header
.EventList
,
1059 (PVOID
)&This
->Header
.EventListLock
,
1061 FilterInstance
->Descriptor
->AutomationTable
->EventItemSize
);
1065 /* disable event handler */
1066 Status
= KsDisableEvent(Irp
, &This
->Header
.EventList
, KSEVENTS_SPINLOCK
, &This
->Header
.EventListLock
);
1070 RtlStringFromGUID(&Property
->Set
, &GuidString
);
1071 DPRINT("IKsFilter_DispatchDeviceIoControl property PinCount %x\n", FilterInstance
->Descriptor
->PinDescriptorsCount
);
1072 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
);
1073 RtlFreeUnicodeString(&GuidString
);
1075 /* release filter */
1076 Filter
->lpVtbl
->Release(Filter
);
1078 /* release control mutex */
1079 KeReleaseMutex(This
->Header
.ControlMutex
, FALSE
);
1081 if (Status
!= STATUS_PENDING
)
1083 Irp
->IoStatus
.Status
= Status
;
1084 CompleteRequest(Irp
, IO_NO_INCREMENT
);
1091 static KSDISPATCH_TABLE DispatchTable
=
1093 IKsFilter_DispatchDeviceIoControl
,
1094 KsDispatchInvalidDeviceRequest
,
1095 KsDispatchInvalidDeviceRequest
,
1096 KsDispatchInvalidDeviceRequest
,
1097 IKsFilter_DispatchClose
,
1098 KsDispatchQuerySecurity
,
1099 KsDispatchSetSecurity
,
1100 KsDispatchFastIoDeviceControlFailure
,
1101 KsDispatchFastReadFailure
,
1102 KsDispatchFastReadFailure
,
1107 IKsFilter_CreateDescriptors(
1108 IKsFilterImpl
* This
,
1109 KSFILTER_DESCRIPTOR
* FilterDescriptor
)
1113 PKSNODE_DESCRIPTOR NodeDescriptor
;
1115 /* initialize pin descriptors */
1116 This
->FirstPin
= NULL
;
1117 This
->PinInstanceCount
= NULL
;
1118 This
->ProcessPinIndex
= NULL
;
1120 /* initialize topology descriptor */
1121 This
->Topology
.CategoriesCount
= FilterDescriptor
->CategoriesCount
;
1122 This
->Topology
.Categories
= FilterDescriptor
->Categories
;
1123 This
->Topology
.TopologyNodesCount
= FilterDescriptor
->NodeDescriptorsCount
;
1124 This
->Topology
.TopologyConnectionsCount
= FilterDescriptor
->ConnectionsCount
;
1125 This
->Topology
.TopologyConnections
= FilterDescriptor
->Connections
;
1127 /* are there any templates */
1128 if (FilterDescriptor
->PinDescriptorsCount
)
1131 ASSERT(FilterDescriptor
->PinDescriptors
);
1133 /* FIXME handle variable sized pin descriptors */
1134 ASSERT(FilterDescriptor
->PinDescriptorSize
== sizeof(KSPIN_DESCRIPTOR_EX
));
1136 /* store pin descriptors ex */
1137 Status
= _KsEdit(This
->Filter
.Bag
, (PVOID
*)&This
->Filter
.Descriptor
->PinDescriptors
, FilterDescriptor
->PinDescriptorSize
* FilterDescriptor
->PinDescriptorsCount
,
1138 FilterDescriptor
->PinDescriptorSize
* FilterDescriptor
->PinDescriptorsCount
, 0);
1140 if (!NT_SUCCESS(Status
))
1142 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status
);
1146 /* store pin instance count */
1147 Status
= _KsEdit(This
->Filter
.Bag
, (PVOID
*)&This
->PinInstanceCount
, sizeof(ULONG
) * FilterDescriptor
->PinDescriptorsCount
,
1148 sizeof(ULONG
) * FilterDescriptor
->PinDescriptorsCount
, 0);
1150 if (!NT_SUCCESS(Status
))
1152 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status
);
1156 /* store instantiated pin arrays */
1157 Status
= _KsEdit(This
->Filter
.Bag
, (PVOID
*)&This
->FirstPin
, sizeof(PVOID
) * FilterDescriptor
->PinDescriptorsCount
,
1158 sizeof(PVOID
) * FilterDescriptor
->PinDescriptorsCount
, 0);
1160 if (!NT_SUCCESS(Status
))
1162 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status
);
1166 /* add new pin factory */
1167 RtlMoveMemory((PVOID
)This
->Filter
.Descriptor
->PinDescriptors
, FilterDescriptor
->PinDescriptors
, FilterDescriptor
->PinDescriptorSize
* FilterDescriptor
->PinDescriptorsCount
);
1169 /* allocate process pin index */
1170 Status
= _KsEdit(This
->Filter
.Bag
, (PVOID
*)&This
->ProcessPinIndex
, sizeof(KSPROCESSPIN_INDEXENTRY
) * FilterDescriptor
->PinDescriptorsCount
,
1171 sizeof(KSPROCESSPIN_INDEXENTRY
) * FilterDescriptor
->PinDescriptorsCount
, 0);
1173 if (!NT_SUCCESS(Status
))
1175 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status
);
1182 if (FilterDescriptor
->ConnectionsCount
)
1184 /* modify connections array */
1185 Status
= _KsEdit(This
->Filter
.Bag
,
1186 (PVOID
*)&This
->Filter
.Descriptor
->Connections
,
1187 FilterDescriptor
->ConnectionsCount
* sizeof(KSTOPOLOGY_CONNECTION
),
1188 FilterDescriptor
->ConnectionsCount
* sizeof(KSTOPOLOGY_CONNECTION
),
1191 This
->Topology
.TopologyConnections
= This
->Filter
.Descriptor
->Connections
;
1192 This
->Topology
.TopologyConnectionsCount
= ((PKSFILTER_DESCRIPTOR
)This
->Filter
.Descriptor
)->ConnectionsCount
= FilterDescriptor
->ConnectionsCount
;
1195 if (FilterDescriptor
->NodeDescriptorsCount
)
1198 ASSERT(FilterDescriptor
->NodeDescriptors
);
1201 ASSERT(FilterDescriptor
->NodeDescriptorSize
>= sizeof(KSNODE_DESCRIPTOR
));
1203 This
->Topology
.TopologyNodes
= AllocateItem(NonPagedPool
, sizeof(GUID
) * FilterDescriptor
->NodeDescriptorsCount
);
1204 /* allocate topology node types array */
1205 if (!This
->Topology
.TopologyNodes
)
1207 DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor
->NodeDescriptorsCount
);
1208 return STATUS_INSUFFICIENT_RESOURCES
;
1211 This
->Topology
.TopologyNodesNames
= AllocateItem(NonPagedPool
, sizeof(GUID
) * FilterDescriptor
->NodeDescriptorsCount
);
1212 /* allocate topology names array */
1213 if (!This
->Topology
.TopologyNodesNames
)
1215 FreeItem((PVOID
)This
->Topology
.TopologyNodes
);
1216 DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor
->NodeDescriptorsCount
);
1217 return STATUS_INSUFFICIENT_RESOURCES
;
1220 DPRINT("NodeDescriptorCount %lu\n", FilterDescriptor
->NodeDescriptorsCount
);
1221 NodeDescriptor
= (PKSNODE_DESCRIPTOR
)FilterDescriptor
->NodeDescriptors
;
1222 for(Index
= 0; Index
< FilterDescriptor
->NodeDescriptorsCount
; Index
++)
1224 DPRINT("Index %lu Type %p Name %p\n", Index
, NodeDescriptor
->Type
, NodeDescriptor
->Name
);
1226 /* copy topology type */
1227 if (NodeDescriptor
->Type
)
1228 RtlMoveMemory((PVOID
)&This
->Topology
.TopologyNodes
[Index
], NodeDescriptor
->Type
, sizeof(GUID
));
1230 /* copy topology name */
1231 if (NodeDescriptor
->Name
)
1232 RtlMoveMemory((PVOID
)&This
->Topology
.TopologyNodesNames
[Index
], NodeDescriptor
->Name
, sizeof(GUID
));
1234 // next node descriptor
1235 NodeDescriptor
= (PKSNODE_DESCRIPTOR
)((ULONG_PTR
)NodeDescriptor
+ FilterDescriptor
->NodeDescriptorSize
);
1239 return STATUS_SUCCESS
;
1243 IKsFilter_CopyFilterDescriptor(
1244 IKsFilterImpl
* This
,
1245 const KSFILTER_DESCRIPTOR
* FilterDescriptor
)
1248 KSAUTOMATION_TABLE AutomationTable
;
1250 This
->Filter
.Descriptor
= AllocateItem(NonPagedPool
, sizeof(KSFILTER_DESCRIPTOR
));
1251 if (!This
->Filter
.Descriptor
)
1252 return STATUS_INSUFFICIENT_RESOURCES
;
1254 Status
= KsAddItemToObjectBag(This
->Filter
.Bag
, (PVOID
)This
->Filter
.Descriptor
, NULL
);
1255 if (!NT_SUCCESS(Status
))
1257 FreeItem((PVOID
)This
->Filter
.Descriptor
);
1258 This
->Filter
.Descriptor
= NULL
;
1259 return STATUS_INSUFFICIENT_RESOURCES
;
1262 /* copy filter descriptor fields */
1263 RtlMoveMemory((PVOID
)This
->Filter
.Descriptor
, FilterDescriptor
, sizeof(KSFILTER_DESCRIPTOR
));
1265 /* zero automation table */
1266 RtlZeroMemory(&AutomationTable
, sizeof(KSAUTOMATION_TABLE
));
1268 /* setup filter property sets */
1269 AutomationTable
.PropertyItemSize
= sizeof(KSPROPERTY_ITEM
);
1270 AutomationTable
.PropertySetsCount
= 2;
1271 AutomationTable
.PropertySets
= FilterPropertySet
;
1273 /* merge filter automation table */
1274 Status
= KsMergeAutomationTables((PKSAUTOMATION_TABLE
*)&This
->Filter
.Descriptor
->AutomationTable
, (PKSAUTOMATION_TABLE
)FilterDescriptor
->AutomationTable
, &AutomationTable
, This
->Filter
.Bag
);
1285 PKSPIN NextPin
, CurPin
;
1286 PKSBASIC_HEADER BasicHeader
;
1287 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1290 ASSERT(Pin
->Id
< This
->Filter
.Descriptor
->PinDescriptorsCount
);
1292 if (This
->FirstPin
[Pin
->Id
] == NULL
)
1294 /* welcome first pin */
1295 This
->FirstPin
[Pin
->Id
] = Pin
;
1296 This
->PinInstanceCount
[Pin
->Id
]++;
1301 CurPin
= This
->FirstPin
[Pin
->Id
];
1305 /* get next instantiated pin */
1306 NextPin
= KsPinGetNextSiblingPin(CurPin
);
1312 }while(NextPin
!= NULL
);
1314 /* get basic header */
1315 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)CurPin
- sizeof(KSBASIC_HEADER
));
1318 BasicHeader
->Next
.Pin
= Pin
;
1322 IKsFilter_RemovePin(
1326 PKSPIN NextPin
, CurPin
, LastPin
;
1327 PKSBASIC_HEADER BasicHeader
;
1328 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1331 ASSERT(Pin
->Id
< This
->Filter
.Descriptor
->PinDescriptorsCount
);
1334 CurPin
= This
->FirstPin
[Pin
->Id
];
1339 /* get next instantiated pin */
1340 NextPin
= KsPinGetNextSiblingPin(CurPin
);
1346 /* get basic header of last pin */
1347 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)LastPin
- sizeof(KSBASIC_HEADER
));
1349 BasicHeader
->Next
.Pin
= NextPin
;
1353 /* erase last pin */
1354 This
->FirstPin
[Pin
->Id
] = NextPin
;
1356 /* decrement pin instance count */
1357 This
->PinInstanceCount
[Pin
->Id
]--;
1367 }while(NextPin
!= NULL
);
1376 IKsFilter_DispatchCreatePin(
1377 IN PDEVICE_OBJECT DeviceObject
,
1380 IKsFilterImpl
* This
;
1381 PKSOBJECT_CREATE_ITEM CreateItem
;
1382 PKSPIN_CONNECT Connect
;
1385 DPRINT("IKsFilter_DispatchCreatePin\n");
1387 /* get the create item */
1388 CreateItem
= KSCREATE_ITEM_IRP_STORAGE(Irp
);
1390 /* get the filter object */
1391 This
= (IKsFilterImpl
*)CreateItem
->Context
;
1394 ASSERT(This
->Header
.Type
== KsObjectTypeFilter
);
1396 /* acquire control mutex */
1397 KeWaitForSingleObject(This
->Header
.ControlMutex
, Executive
, KernelMode
, FALSE
, NULL
);
1399 /* now validate the connect request */
1400 Status
= KspValidateConnectRequest(Irp
, This
->Filter
.Descriptor
->PinDescriptorsCount
, (PVOID
)This
->Filter
.Descriptor
->PinDescriptors
, This
->Filter
.Descriptor
->PinDescriptorSize
, &Connect
);
1402 DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest %lx\n", Status
);
1404 if (NT_SUCCESS(Status
))
1407 ASSERT(Connect
->PinId
< This
->Filter
.Descriptor
->PinDescriptorsCount
);
1409 DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest PinId %lu CurrentInstanceCount %lu MaxPossible %lu\n", Connect
->PinId
,
1410 This
->PinInstanceCount
[Connect
->PinId
],
1411 This
->Filter
.Descriptor
->PinDescriptors
[Connect
->PinId
].InstancesPossible
);
1413 if (This
->PinInstanceCount
[Connect
->PinId
] < This
->Filter
.Descriptor
->PinDescriptors
[Connect
->PinId
].InstancesPossible
)
1415 /* create the pin */
1416 Status
= KspCreatePin(DeviceObject
, Irp
, This
->Header
.KsDevice
, This
->FilterFactory
, (IKsFilter
*)&This
->Header
.OuterUnknown
, Connect
, (KSPIN_DESCRIPTOR_EX
*)&This
->Filter
.Descriptor
->PinDescriptors
[Connect
->PinId
]);
1418 DPRINT("IKsFilter_DispatchCreatePin KspCreatePin %lx\n", Status
);
1422 /* maximum instance count reached, bye-bye */
1423 Status
= STATUS_UNSUCCESSFUL
;
1424 DPRINT("IKsFilter_DispatchCreatePin MaxInstance %lu CurInstance %lu %lx\n", This
->Filter
.Descriptor
->PinDescriptors
[Connect
->PinId
].InstancesPossible
, This
->PinInstanceCount
[Connect
->PinId
]);
1428 /* release control mutex */
1429 KeReleaseMutex(This
->Header
.ControlMutex
, FALSE
);
1431 if (Status
!= STATUS_PENDING
)
1433 /* complete request */
1434 Irp
->IoStatus
.Status
= Status
;
1435 CompleteRequest(Irp
, IO_NO_INCREMENT
);
1439 DPRINT("IKsFilter_DispatchCreatePin Result %lx\n", Status
);
1445 IKsFilter_DispatchCreateNode(
1446 IN PDEVICE_OBJECT DeviceObject
,
1450 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
1451 CompleteRequest(Irp
, IO_NO_INCREMENT
);
1452 return STATUS_UNSUCCESSFUL
;
1457 IKsFilter_AttachFilterToFilterFactory(
1458 IKsFilterImpl
* This
,
1459 PKSFILTERFACTORY FilterFactory
)
1461 PKSBASIC_HEADER BasicHeader
;
1465 /* get filter factory basic header */
1466 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)FilterFactory
- sizeof(KSBASIC_HEADER
));
1469 ASSERT(BasicHeader
->Type
== KsObjectTypeFilterFactory
);
1471 if (BasicHeader
->FirstChild
.FilterFactory
== NULL
)
1473 /* welcome first instantiated filter */
1474 BasicHeader
->FirstChild
.Filter
= &This
->Filter
;
1478 /* set to first entry */
1479 Filter
= BasicHeader
->FirstChild
.Filter
;
1483 /* get basic header */
1484 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)Filter
- sizeof(KSBASIC_HEADER
));
1486 ASSERT(BasicHeader
->Type
== KsObjectTypeFilter
);
1488 if (BasicHeader
->Next
.Filter
)
1490 /* iterate to next filter factory */
1491 Filter
= BasicHeader
->Next
.Filter
;
1495 /* found last entry */
1500 /* attach filter factory */
1501 BasicHeader
->Next
.Filter
= &This
->Filter
;
1505 IKsFilter_RemoveFilterFromFilterFactory(
1506 IKsFilterImpl
* This
,
1507 PKSFILTERFACTORY FilterFactory
)
1509 PKSBASIC_HEADER BasicHeader
;
1510 PKSFILTER Filter
, LastFilter
;
1512 /* get filter factory basic header */
1513 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)FilterFactory
- sizeof(KSBASIC_HEADER
));
1516 ASSERT(BasicHeader
->Type
== KsObjectTypeFilterFactory
);
1517 ASSERT(BasicHeader
->FirstChild
.Filter
!= NULL
);
1520 /* set to first entry */
1521 Filter
= BasicHeader
->FirstChild
.Filter
;
1526 if (Filter
== &This
->Filter
)
1530 /* get basic header */
1531 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)LastFilter
- sizeof(KSBASIC_HEADER
));
1532 /* remove filter instance */
1533 BasicHeader
->Next
.Filter
= This
->Header
.Next
.Filter
;
1538 /* remove filter instance */
1539 BasicHeader
->FirstChild
.Filter
= This
->Header
.Next
.Filter
;
1544 /* get basic header */
1545 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)Filter
- sizeof(KSBASIC_HEADER
));
1547 ASSERT(BasicHeader
->Type
== KsObjectTypeFilter
);
1549 LastFilter
= Filter
;
1550 if (BasicHeader
->Next
.Filter
)
1552 /* iterate to next filter factory */
1553 Filter
= BasicHeader
->Next
.Filter
;
1557 /* filter is not in list */
1566 IKsFilter_FilterCentricWorker(
1569 IKsProcessingObject
* Object
= (IKsProcessingObject
*)Ctx
;
1575 Object
->lpVtbl
->ProcessingObjectWork(Object
);
1581 IN PDEVICE_OBJECT DeviceObject
,
1583 IN IKsFilterFactory
*iface
)
1585 IKsFilterImpl
* This
;
1586 IKsDevice
*KsDevice
;
1587 PKSFILTERFACTORY Factory
;
1588 PIO_STACK_LOCATION IoStack
;
1589 PDEVICE_EXTENSION DeviceExtension
;
1591 PKSOBJECT_CREATE_ITEM CreateItem
;
1593 /* get device extension */
1594 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1596 /* get the filter factory */
1597 Factory
= iface
->lpVtbl
->GetStruct(iface
);
1599 if (!Factory
|| !Factory
->FilterDescriptor
)
1601 /* Sorry it just will not work */
1602 return STATUS_UNSUCCESSFUL
;
1605 if (Factory
->FilterDescriptor
->Flags
& KSFILTER_FLAG_DENY_USERMODE_ACCESS
)
1607 if (Irp
->RequestorMode
== UserMode
)
1609 /* filter not accessible from user mode */
1610 DPRINT1("Access denied\n");
1611 return STATUS_UNSUCCESSFUL
;
1615 /* allocate filter instance */
1616 This
= AllocateItem(NonPagedPool
, sizeof(IKsFilterImpl
));
1619 DPRINT1("KspCreateFilter OutOfMemory\n");
1620 return STATUS_INSUFFICIENT_RESOURCES
;
1623 /* initialize object bag */
1624 This
->Filter
.Bag
= AllocateItem(NonPagedPool
, sizeof(KSIOBJECT_BAG
));
1625 if (!This
->Filter
.Bag
)
1629 DPRINT1("KspCreateFilter OutOfMemory\n");
1630 return STATUS_INSUFFICIENT_RESOURCES
;
1632 KsDevice
= (IKsDevice
*)&DeviceExtension
->DeviceHeader
->BasicHeader
.OuterUnknown
;
1633 KsDevice
->lpVtbl
->InitializeObjectBag(KsDevice
, (PKSIOBJECT_BAG
)This
->Filter
.Bag
, NULL
);
1635 /* copy filter descriptor */
1636 Status
= IKsFilter_CopyFilterDescriptor(This
, Factory
->FilterDescriptor
);
1637 if (!NT_SUCCESS(Status
))
1639 /* not enough memory */
1640 FreeItem(This
->Filter
.Bag
);
1642 DPRINT("KspCreateFilter IKsFilter_CopyFilterDescriptor failed %lx\n", Status
);
1643 return STATUS_INSUFFICIENT_RESOURCES
;
1646 /* get current irp stack */
1647 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1649 /* allocate create items */
1650 CreateItem
= AllocateItem(NonPagedPool
, sizeof(KSOBJECT_CREATE_ITEM
) * 2);
1654 FreeItem(This
->Filter
.Bag
);
1656 DPRINT1("KspCreateFilter OutOfMemory\n");
1657 return STATUS_INSUFFICIENT_RESOURCES
;
1660 /* initialize pin create item */
1661 CreateItem
[0].Create
= IKsFilter_DispatchCreatePin
;
1662 CreateItem
[0].Context
= (PVOID
)This
;
1663 CreateItem
[0].Flags
= KSCREATE_ITEM_FREEONSTOP
;
1664 RtlInitUnicodeString(&CreateItem
[0].ObjectClass
, KSSTRING_Pin
);
1665 /* initialize node create item */
1666 CreateItem
[1].Create
= IKsFilter_DispatchCreateNode
;
1667 CreateItem
[1].Context
= (PVOID
)This
;
1668 CreateItem
[1].Flags
= KSCREATE_ITEM_FREEONSTOP
;
1669 RtlInitUnicodeString(&CreateItem
[1].ObjectClass
, KSSTRING_TopologyNode
);
1672 /* initialize filter instance */
1674 This
->Header
.OuterUnknown
= (PUNKNOWN
)&vt_IKsFilter
;
1675 This
->lpVtblKsControl
= &vt_IKsControl
;
1676 This
->lpVtblKsProcessingObject
= &vt_IKsProcessingObject
;
1678 This
->Factory
= Factory
;
1679 This
->FilterFactory
= iface
;
1680 This
->FileObject
= IoStack
->FileObject
;
1681 KeInitializeMutex(&This
->ProcessingMutex
, 0);
1683 /* initialize basic header */
1684 This
->Header
.KsDevice
= &DeviceExtension
->DeviceHeader
->KsDevice
;
1685 This
->Header
.Parent
.KsFilterFactory
= iface
->lpVtbl
->GetStruct(iface
);
1686 This
->Header
.Type
= KsObjectTypeFilter
;
1687 This
->Header
.ControlMutex
= &This
->ControlMutex
;
1688 KeInitializeMutex(This
->Header
.ControlMutex
, 0);
1689 InitializeListHead(&This
->Header
.EventList
);
1690 KeInitializeSpinLock(&This
->Header
.EventListLock
);
1692 /* initialize and gate */
1693 KsGateInitializeAnd(&This
->Gate
, NULL
);
1695 /* FIXME initialize and gate based on pin flags */
1697 /* initialize work item */
1698 ExInitializeWorkItem(&This
->WorkItem
, IKsFilter_FilterCentricWorker
, (PVOID
)This
->lpVtblKsProcessingObject
);
1700 /* allocate counted work item */
1701 Status
= KsRegisterCountedWorker(HyperCriticalWorkQueue
, &This
->WorkItem
, &This
->Worker
);
1702 if (!NT_SUCCESS(Status
))
1704 /* what can go wrong, goes wrong */
1705 DPRINT1("KsRegisterCountedWorker failed with %lx\n", Status
);
1707 FreeItem(CreateItem
);
1711 /* allocate the stream descriptors */
1712 Status
= IKsFilter_CreateDescriptors(This
, (PKSFILTER_DESCRIPTOR
)Factory
->FilterDescriptor
);
1713 if (!NT_SUCCESS(Status
))
1715 /* what can go wrong, goes wrong */
1716 DPRINT1("IKsFilter_CreateDescriptors failed with %lx\n", Status
);
1717 KsUnregisterWorker(This
->Worker
);
1719 FreeItem(CreateItem
);
1725 /* does the filter have a filter dispatch */
1726 if (Factory
->FilterDescriptor
->Dispatch
)
1728 /* does it have a create routine */
1729 if (Factory
->FilterDescriptor
->Dispatch
->Create
)
1731 /* now let driver initialize the filter instance */
1733 ASSERT(This
->Header
.KsDevice
);
1734 ASSERT(This
->Header
.KsDevice
->Started
);
1735 Status
= Factory
->FilterDescriptor
->Dispatch
->Create(&This
->Filter
, Irp
);
1737 if (!NT_SUCCESS(Status
) && Status
!= STATUS_PENDING
)
1739 /* driver failed to initialize */
1740 DPRINT1("Driver: Status %x\n", Status
);
1742 /* free filter instance */
1743 KsUnregisterWorker(This
->Worker
);
1745 FreeItem(CreateItem
);
1751 /* now allocate the object header */
1752 Status
= KsAllocateObjectHeader((PVOID
*)&This
->ObjectHeader
, 2, CreateItem
, Irp
, &DispatchTable
);
1753 if (!NT_SUCCESS(Status
))
1755 /* failed to allocate object header */
1756 DPRINT1("Failed to allocate object header %x\n", Status
);
1761 /* initialize object header extra fields */
1762 This
->ObjectHeader
->Type
= KsObjectTypeFilter
;
1763 This
->ObjectHeader
->Unknown
= (PUNKNOWN
)&This
->Header
.OuterUnknown
;
1764 This
->ObjectHeader
->ObjectType
= (PVOID
)&This
->Filter
;
1766 /* attach filter to filter factory */
1767 IKsFilter_AttachFilterToFilterFactory(This
, This
->Header
.Parent
.KsFilterFactory
);
1769 /* completed initialization */
1770 DPRINT1("KspCreateFilter done %lx KsDevice %p\n", Status
, This
->Header
.KsDevice
);
1780 KsFilterAcquireProcessingMutex(
1781 IN PKSFILTER Filter
)
1783 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1785 KeWaitForSingleObject(&This
->ProcessingMutex
, Executive
, KernelMode
, FALSE
, NULL
);
1794 KsFilterReleaseProcessingMutex(
1795 IN PKSFILTER Filter
)
1797 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1799 KeReleaseMutex(&This
->ProcessingMutex
, FALSE
);
1809 KsFilterAddTopologyConnections (
1810 IN PKSFILTER Filter
,
1811 IN ULONG NewConnectionsCount
,
1812 IN
const KSTOPOLOGY_CONNECTION
*const NewTopologyConnections
)
1816 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1818 DPRINT("KsFilterAddTopologyConnections\n");
1820 ASSERT(This
->Filter
.Descriptor
);
1821 Count
= This
->Filter
.Descriptor
->ConnectionsCount
+ NewConnectionsCount
;
1824 /* modify connections array */
1825 Status
= _KsEdit(This
->Filter
.Bag
,
1826 (PVOID
*)&This
->Filter
.Descriptor
->Connections
,
1827 Count
* sizeof(KSTOPOLOGY_CONNECTION
),
1828 This
->Filter
.Descriptor
->ConnectionsCount
* sizeof(KSTOPOLOGY_CONNECTION
),
1831 if (!NT_SUCCESS(Status
))
1834 DPRINT("KsFilterAddTopologyConnections KsEdit failed with %lx\n", Status
);
1838 /* FIXME verify connections */
1840 /* copy new connections */
1841 RtlMoveMemory((PVOID
)&This
->Filter
.Descriptor
->Connections
[This
->Filter
.Descriptor
->ConnectionsCount
],
1842 NewTopologyConnections
,
1843 NewConnectionsCount
* sizeof(KSTOPOLOGY_CONNECTION
));
1845 /* update topology */
1846 This
->Topology
.TopologyConnectionsCount
+= NewConnectionsCount
;
1847 ((PKSFILTER_DESCRIPTOR
)This
->Filter
.Descriptor
)->ConnectionsCount
+= NewConnectionsCount
;
1848 This
->Topology
.TopologyConnections
= This
->Filter
.Descriptor
->Connections
;
1859 KsFilterAttemptProcessing(
1860 IN PKSFILTER Filter
,
1861 IN BOOLEAN Asynchronous
)
1864 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1867 Gate
= This
->lpVtblKsProcessingObject
->GetAndGate((IKsProcessingObject
*)This
->lpVtblKsProcessingObject
);
1869 if (!KsGateCaptureThreshold(Gate
))
1871 /* filter control gate is closed */
1874 DPRINT1("processing\n");
1875 /* try initiate processing */
1876 This
->lpVtblKsProcessingObject
->Process((IKsProcessingObject
*)This
->lpVtblKsProcessingObject
, Asynchronous
);
1885 KsFilterCreateNode (
1886 IN PKSFILTER Filter
,
1887 IN
const KSNODE_DESCRIPTOR
*const NodeDescriptor
,
1891 return STATUS_NOT_IMPLEMENTED
;
1900 KsFilterCreatePinFactory (
1901 IN PKSFILTER Filter
,
1902 IN
const KSPIN_DESCRIPTOR_EX
*const InPinDescriptor
,
1907 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1909 DPRINT("KsFilterCreatePinFactory\n");
1911 /* calculate new count */
1912 Count
= This
->Filter
.Descriptor
->PinDescriptorsCount
+ 1;
1915 ASSERT(This
->Filter
.Descriptor
->PinDescriptorSize
== sizeof(KSPIN_DESCRIPTOR_EX
));
1917 /* modify pin descriptors ex array */
1918 Status
= _KsEdit(This
->Filter
.Bag
, (PVOID
*)&This
->Filter
.Descriptor
->PinDescriptors
, Count
* This
->Filter
.Descriptor
->PinDescriptorSize
, This
->Filter
.Descriptor
->PinDescriptorsCount
* This
->Filter
.Descriptor
->PinDescriptorSize
, 0);
1919 if (!NT_SUCCESS(Status
))
1922 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status
);
1926 /* modify pin instance count array */
1927 Status
= _KsEdit(This
->Filter
.Bag
,(PVOID
*)&This
->PinInstanceCount
, sizeof(ULONG
) * Count
, sizeof(ULONG
) * This
->Filter
.Descriptor
->PinDescriptorsCount
, 0);
1928 if (!NT_SUCCESS(Status
))
1931 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status
);
1935 /* modify first pin array */
1936 Status
= _KsEdit(This
->Filter
.Bag
,(PVOID
*)&This
->FirstPin
, sizeof(PVOID
) * Count
, sizeof(PVOID
) * This
->Filter
.Descriptor
->PinDescriptorsCount
, 0);
1937 if (!NT_SUCCESS(Status
))
1940 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status
);
1944 /* add new pin factory */
1945 RtlMoveMemory((PVOID
)&This
->Filter
.Descriptor
->PinDescriptors
[This
->Filter
.Descriptor
->PinDescriptorsCount
], InPinDescriptor
, sizeof(KSPIN_DESCRIPTOR_EX
));
1947 /* allocate process pin index */
1948 Status
= _KsEdit(This
->Filter
.Bag
, (PVOID
*)&This
->ProcessPinIndex
, sizeof(KSPROCESSPIN_INDEXENTRY
) * Count
,
1949 sizeof(KSPROCESSPIN_INDEXENTRY
) * This
->Filter
.Descriptor
->PinDescriptorsCount
, 0);
1951 if (!NT_SUCCESS(Status
))
1953 DPRINT("KsFilterCreatePinFactory _KsEdit failed %lx\n", Status
);
1957 /* store new pin id */
1958 *PinID
= This
->Filter
.Descriptor
->PinDescriptorsCount
;
1960 /* increment pin descriptor count */
1961 ((PKSFILTER_DESCRIPTOR
)This
->Filter
.Descriptor
)->PinDescriptorsCount
++;
1964 DPRINT("KsFilterCreatePinFactory done\n");
1965 return STATUS_SUCCESS
;
1976 IN PKSFILTER Filter
)
1978 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1980 /* return and-gate */
1990 KsFilterGetChildPinCount(
1991 IN PKSFILTER Filter
,
1994 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1996 if (PinId
>= This
->Filter
.Descriptor
->PinDescriptorsCount
)
1998 /* index is out of bounds */
2001 /* return pin instance count */
2002 return This
->PinInstanceCount
[PinId
];
2011 KsFilterGetFirstChildPin(
2012 IN PKSFILTER Filter
,
2015 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
2017 if (PinId
>= This
->Filter
.Descriptor
->PinDescriptorsCount
)
2019 /* index is out of bounds */
2023 /* return first pin index */
2024 return This
->FirstPin
[PinId
];
2033 KsFilterRegisterPowerCallbacks(
2034 IN PKSFILTER Filter
,
2035 IN PFNKSFILTERPOWER Sleep OPTIONAL
,
2036 IN PFNKSFILTERPOWER Wake OPTIONAL
)
2038 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
2040 This
->Sleep
= Sleep
;
2053 PIO_STACK_LOCATION IoStack
;
2054 PKSIOBJECT_HEADER ObjectHeader
;
2056 DPRINT("KsGetFilterFromIrp\n");
2058 /* get current irp stack location */
2059 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
2062 ASSERT(IoStack
->FileObject
);
2064 /* get object header */
2065 ObjectHeader
= (PKSIOBJECT_HEADER
)IoStack
->FileObject
->FsContext2
;
2067 if (ObjectHeader
->Type
== KsObjectTypeFilter
)
2069 /* irp is targeted at the filter */
2070 return (PKSFILTER
)ObjectHeader
->ObjectType
;
2072 else if (ObjectHeader
->Type
== KsObjectTypePin
)
2074 /* irp is for a pin */
2075 return KsPinGetParentFilter((PKSPIN
)ObjectHeader
->ObjectType
);
2079 /* irp is unappropiate to retrieve a filter */