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 IKsFilterVtbl
*lpVtbl
;
18 IKsControlVtbl
*lpVtblKsControl
;
19 IKsFilterFactory
* FilterFactory
;
22 PKSIOBJECT_HEADER ObjectHeader
;
24 KSPIN_DESCRIPTOR
* PinDescriptors
;
25 ULONG PinDescriptorCount
;
26 PKSFILTERFACTORY Factory
;
27 PFILE_OBJECT FileObject
;
28 KMUTEX ProcessingMutex
;
31 PFNKSFILTERPOWER Sleep
;
32 PFNKSFILTERPOWER Wake
;
34 ULONG
*PinInstanceCount
;
37 const GUID IID_IKsControl
= {0x28F54685L
, 0x06FD, 0x11D2, {0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
38 const GUID IID_IKsFilter
= {0x3ef6ee44L
, 0x0D41, 0x11d2, {0xbe, 0xDA, 0x00, 0xc0, 0x4f, 0x8e, 0xF4, 0x57}};
39 const GUID KSPROPSETID_Topology
= {0x720D4AC0L
, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
40 const GUID KSPROPSETID_Pin
= {0x8C134960L
, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
43 DEFINE_KSPROPERTY_TOPOLOGYSET(IKsFilterTopologySet
, KspTopologyPropertyHandler
);
44 DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(IKsFilterPinSet
, KspPinPropertyHandler
, KspPinPropertyHandler
, KspPinPropertyHandler
);
46 KSPROPERTY_SET FilterPropertySet
[] =
49 &KSPROPSETID_Topology
,
50 sizeof(IKsFilterTopologySet
) / sizeof(KSPROPERTY_ITEM
),
51 (const KSPROPERTY_ITEM
*)&IKsFilterTopologySet
,
57 sizeof(IKsFilterPinSet
) / sizeof(KSPROPERTY_ITEM
),
58 (const KSPROPERTY_ITEM
*)&IKsFilterPinSet
,
66 IKsControl_fnQueryInterface(
71 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsControl
);
73 if (IsEqualGUIDAligned(refiid
, &IID_IUnknown
))
75 *Output
= &This
->lpVtbl
;
76 _InterlockedIncrement(&This
->ref
);
77 return STATUS_SUCCESS
;
79 return STATUS_UNSUCCESSFUL
;
87 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsControl
);
89 return InterlockedIncrement(&This
->ref
);
97 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsControl
);
99 InterlockedDecrement(&This
->ref
);
101 /* Return new reference count */
107 IKsControl_fnKsProperty(
109 IN PKSPROPERTY Property
,
110 IN ULONG PropertyLength
,
111 IN OUT PVOID PropertyData
,
113 OUT ULONG
* BytesReturned
)
115 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsControl
);
117 return KsSynchronousIoControlDevice(This
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, Property
, PropertyLength
, PropertyData
, DataLength
, BytesReturned
);
123 IKsControl_fnKsMethod(
126 IN ULONG MethodLength
,
127 IN OUT PVOID MethodData
,
129 OUT ULONG
* BytesReturned
)
131 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsControl
);
133 return KsSynchronousIoControlDevice(This
->FileObject
, KernelMode
, IOCTL_KS_METHOD
, Method
, MethodLength
, MethodData
, DataLength
, BytesReturned
);
139 IKsControl_fnKsEvent(
141 IN PKSEVENT Event OPTIONAL
,
142 IN ULONG EventLength
,
143 IN OUT PVOID EventData
,
145 OUT ULONG
* BytesReturned
)
147 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsControl
);
151 return KsSynchronousIoControlDevice(This
->FileObject
, KernelMode
, IOCTL_KS_ENABLE_EVENT
, Event
, EventLength
, EventData
, DataLength
, BytesReturned
);
155 return KsSynchronousIoControlDevice(This
->FileObject
, KernelMode
, IOCTL_KS_DISABLE_EVENT
, EventData
, DataLength
, NULL
, 0, BytesReturned
);
160 static IKsControlVtbl vt_IKsControl
=
162 IKsControl_fnQueryInterface
,
164 IKsControl_fnRelease
,
165 IKsControl_fnKsProperty
,
166 IKsControl_fnKsMethod
,
173 IKsFilter_fnQueryInterface(
178 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtbl
);
180 if (IsEqualGUIDAligned(refiid
, &IID_IUnknown
) ||
181 IsEqualGUIDAligned(refiid
, &IID_IKsFilter
))
183 *Output
= &This
->lpVtbl
;
184 _InterlockedIncrement(&This
->ref
);
185 return STATUS_SUCCESS
;
187 else if (IsEqualGUIDAligned(refiid
, &IID_IKsControl
))
189 *Output
= &This
->lpVtblKsControl
;
190 _InterlockedIncrement(&This
->ref
);
191 return STATUS_SUCCESS
;
194 return STATUS_UNSUCCESSFUL
;
202 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtbl
);
204 return InterlockedIncrement(&This
->ref
);
212 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtbl
);
214 InterlockedDecrement(&This
->ref
);
221 /* Return new reference count */
228 IKsFilter_fnGetStruct(
231 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtbl
);
233 return &This
->Filter
;
238 IKsFilter_fnDoAllNecessaryPinsExist(
247 IKsFilter_fnCreateNode(
251 IN PLIST_ENTRY ListEntry
)
254 return STATUS_NOT_IMPLEMENTED
;
259 IKsFilter_fnBindProcessPinsToPipeSection(
261 IN
struct KSPROCESSPIPESECTION
*Section
,
265 OUT PKSGATE
*OutGate
)
268 return STATUS_NOT_IMPLEMENTED
;
273 IKsFilter_fnUnbindProcessPinsFromPipeSection(
275 IN
struct KSPROCESSPIPESECTION
*Section
)
278 return STATUS_NOT_IMPLEMENTED
;
283 IKsFilter_fnAddProcessPin(
285 IN PKSPROCESSPIN ProcessPin
)
288 return STATUS_NOT_IMPLEMENTED
;
293 IKsFilter_fnRemoveProcessPin(
295 IN PKSPROCESSPIN ProcessPin
)
298 return STATUS_NOT_IMPLEMENTED
;
303 IKsFilter_fnReprepareProcessPipeSection(
305 IN
struct KSPROCESSPIPESECTION
*PipeSection
,
314 IKsFilter_fnDeliverResetState(
316 IN
struct KSPROCESSPIPESECTION
*PipeSection
,
317 IN KSRESET ResetState
)
324 IKsFilter_fnIsFrameHolding(
333 IKsFilter_fnRegisterForCopyCallbacks(
341 PKSPROCESSPIN_INDEXENTRY
343 IKsFilter_fnGetProcessDispatch(
350 static IKsFilterVtbl vt_IKsFilter
=
352 IKsFilter_fnQueryInterface
,
355 IKsFilter_fnGetStruct
,
356 IKsFilter_fnDoAllNecessaryPinsExist
,
357 IKsFilter_fnCreateNode
,
358 IKsFilter_fnBindProcessPinsToPipeSection
,
359 IKsFilter_fnUnbindProcessPinsFromPipeSection
,
360 IKsFilter_fnAddProcessPin
,
361 IKsFilter_fnRemoveProcessPin
,
362 IKsFilter_fnReprepareProcessPipeSection
,
363 IKsFilter_fnDeliverResetState
,
364 IKsFilter_fnIsFrameHolding
,
365 IKsFilter_fnRegisterForCopyCallbacks
,
366 IKsFilter_fnGetProcessDispatch
370 IKsFilter_GetFilterFromIrp(
372 OUT IKsFilter
**Filter
)
374 PIO_STACK_LOCATION IoStack
;
375 PKSIOBJECT_HEADER ObjectHeader
;
378 /* get current irp stack */
379 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
382 ASSERT(IoStack
->FileObject
!= NULL
);
384 ObjectHeader
= (PKSIOBJECT_HEADER
)IoStack
->FileObject
->FsContext
;
386 /* sanity is important */
387 ASSERT(ObjectHeader
!= NULL
);
388 ASSERT(ObjectHeader
->Type
== KsObjectTypeFilter
);
389 ASSERT(ObjectHeader
->Unknown
!= NULL
);
391 /* get our private interface */
392 Status
= ObjectHeader
->Unknown
->lpVtbl
->QueryInterface(ObjectHeader
->Unknown
, &IID_IKsFilter
, (PVOID
*)Filter
);
394 if (!NT_SUCCESS(Status
))
396 /* something is wrong here */
397 DPRINT1("KS: Misbehaving filter %p\n", ObjectHeader
->Unknown
);
398 Irp
->IoStatus
.Status
= Status
;
400 /* complete and forget irp */
401 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
410 IKsFilter_DispatchClose(
411 IN PDEVICE_OBJECT DeviceObject
,
415 IKsFilterImpl
* This
;
418 /* obtain filter from object header */
419 Status
= IKsFilter_GetFilterFromIrp(Irp
, &Filter
);
420 if (!NT_SUCCESS(Status
))
423 /* get our real implementation */
424 This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, lpVtbl
);
426 /* does the driver support notifications */
427 if (This
->Factory
->FilterDescriptor
&& This
->Factory
->FilterDescriptor
->Dispatch
&& This
->Factory
->FilterDescriptor
->Dispatch
->Close
)
429 /* call driver's filter close function */
430 Status
= This
->Factory
->FilterDescriptor
->Dispatch
->Close(&This
->Filter
, Irp
);
433 if (Status
!= STATUS_PENDING
)
435 /* save the result */
436 Irp
->IoStatus
.Status
= Status
;
438 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
440 /* remove our instance from the filter factory */
441 This
->FilterFactory
->lpVtbl
->RemoveFilterInstance(This
->FilterFactory
, Filter
);
443 /* now release the acquired interface */
444 Filter
->lpVtbl
->Release(Filter
);
446 /* free object header */
447 KsFreeObjectHeader(This
->ObjectHeader
);
455 KspHandlePropertyInstances(
456 IN PIO_STATUS_BLOCK IoStatus
,
457 IN PKSIDENTIFIER Request
,
459 IN IKsFilterImpl
* This
,
462 KSPIN_CINSTANCES
* Instances
;
463 KSP_PIN
* Pin
= (KSP_PIN
*)Request
;
465 if (!This
->Factory
->FilterDescriptor
|| !This
->Factory
->FilterDescriptor
->PinDescriptorsCount
)
467 /* no filter / pin descriptor */
468 IoStatus
->Status
= STATUS_NOT_IMPLEMENTED
;
469 return STATUS_NOT_IMPLEMENTED
;
472 /* ignore custom structs for now */
473 ASSERT(This
->Factory
->FilterDescriptor
->PinDescriptorSize
== sizeof(KSPIN_DESCRIPTOR_EX
));
474 ASSERT(This
->Factory
->FilterDescriptor
->PinDescriptorsCount
> Pin
->PinId
);
476 Instances
= (KSPIN_CINSTANCES
*)Data
;
477 /* max instance count */
478 Instances
->PossibleCount
= This
->Factory
->FilterDescriptor
->PinDescriptors
[Pin
->PinId
].InstancesPossible
;
479 /* current instance count */
480 Instances
->CurrentCount
= This
->PinInstanceCount
[Pin
->PinId
];
482 IoStatus
->Information
= sizeof(KSPIN_CINSTANCES
);
483 IoStatus
->Status
= STATUS_SUCCESS
;
484 return STATUS_SUCCESS
;
488 KspHandleNecessaryPropertyInstances(
489 IN PIO_STATUS_BLOCK IoStatus
,
490 IN PKSIDENTIFIER Request
,
492 IN IKsFilterImpl
* This
)
495 KSP_PIN
* Pin
= (KSP_PIN
*)Request
;
497 if (!This
->Factory
->FilterDescriptor
|| !This
->Factory
->FilterDescriptor
->PinDescriptorsCount
)
499 /* no filter / pin descriptor */
500 IoStatus
->Status
= STATUS_NOT_IMPLEMENTED
;
501 return STATUS_NOT_IMPLEMENTED
;
504 /* ignore custom structs for now */
505 ASSERT(This
->Factory
->FilterDescriptor
->PinDescriptorSize
== sizeof(KSPIN_DESCRIPTOR_EX
));
506 ASSERT(This
->Factory
->FilterDescriptor
->PinDescriptorsCount
> Pin
->PinId
);
508 Result
= (PULONG
)Data
;
509 *Result
= This
->Factory
->FilterDescriptor
->PinDescriptors
[Pin
->PinId
].InstancesNecessary
;
511 IoStatus
->Information
= sizeof(ULONG
);
512 IoStatus
->Status
= STATUS_SUCCESS
;
513 return STATUS_SUCCESS
;
517 KspHandleDataIntersection(
519 IN PIO_STATUS_BLOCK IoStatus
,
520 IN PKSIDENTIFIER Request
,
523 IN IKsFilterImpl
* This
)
525 PKSMULTIPLE_ITEM MultipleItem
;
526 PKSDATARANGE DataRange
;
527 NTSTATUS Status
= STATUS_NO_MATCH
;
529 KSP_PIN
* Pin
= (KSP_PIN
*)Request
;
531 /* Access parameters */
532 MultipleItem
= (PKSMULTIPLE_ITEM
)(Pin
+ 1);
533 DataRange
= (PKSDATARANGE
)(MultipleItem
+ 1);
535 if (!This
->Factory
->FilterDescriptor
|| !This
->Factory
->FilterDescriptor
->PinDescriptorsCount
)
537 /* no filter / pin descriptor */
538 IoStatus
->Status
= STATUS_NOT_IMPLEMENTED
;
539 return STATUS_NOT_IMPLEMENTED
;
542 /* ignore custom structs for now */
543 ASSERT(This
->Factory
->FilterDescriptor
->PinDescriptorSize
== sizeof(KSPIN_DESCRIPTOR_EX
));
544 ASSERT(This
->Factory
->FilterDescriptor
->PinDescriptorsCount
> Pin
->PinId
);
546 if (This
->Factory
->FilterDescriptor
->PinDescriptors
[Pin
->PinId
].IntersectHandler
== NULL
||
547 This
->Factory
->FilterDescriptor
->PinDescriptors
[Pin
->PinId
].PinDescriptor
.DataRanges
== NULL
||
548 This
->Factory
->FilterDescriptor
->PinDescriptors
[Pin
->PinId
].PinDescriptor
.DataRangesCount
== 0)
550 /* no driver supported intersect handler / no provided data ranges */
551 IoStatus
->Status
= STATUS_NOT_IMPLEMENTED
;
552 return STATUS_NOT_IMPLEMENTED
;
555 for(Index
= 0; Index
< MultipleItem
->Count
; Index
++)
557 /* Call miniport's properitary handler */
558 Status
= This
->Factory
->FilterDescriptor
->PinDescriptors
[Pin
->PinId
].IntersectHandler(NULL
, /* context */
562 (PKSDATAFORMAT
)This
->Factory
->FilterDescriptor
->PinDescriptors
[Pin
->PinId
].PinDescriptor
.DataRanges
,
567 if (Status
== STATUS_SUCCESS
)
569 IoStatus
->Information
= Length
;
572 DataRange
= UlongToPtr(PtrToUlong(DataRange
) + DataRange
->FormatSize
);
575 IoStatus
->Status
= Status
;
581 KspPinPropertyHandler(
583 IN PKSIDENTIFIER Request
,
586 PIO_STACK_LOCATION IoStack
;
587 IKsFilterImpl
* This
;
588 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
590 /* get filter implementation */
591 This
= (IKsFilterImpl
*)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
593 /* get current stack location */
594 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
598 case KSPROPERTY_PIN_CTYPES
:
599 case KSPROPERTY_PIN_DATAFLOW
:
600 case KSPROPERTY_PIN_DATARANGES
:
601 case KSPROPERTY_PIN_INTERFACES
:
602 case KSPROPERTY_PIN_MEDIUMS
:
603 case KSPROPERTY_PIN_COMMUNICATION
:
604 case KSPROPERTY_PIN_CATEGORY
:
605 case KSPROPERTY_PIN_NAME
:
606 case KSPROPERTY_PIN_PROPOSEDATAFORMAT
:
607 Status
= KsPinPropertyHandler(Irp
, Request
, Data
, This
->PinDescriptorCount
, This
->PinDescriptors
);
609 case KSPROPERTY_PIN_GLOBALCINSTANCES
:
610 Status
= KspHandlePropertyInstances(&Irp
->IoStatus
, Request
, Data
, This
, TRUE
);
612 case KSPROPERTY_PIN_CINSTANCES
:
613 Status
= KspHandlePropertyInstances(&Irp
->IoStatus
, Request
, Data
, This
, FALSE
);
615 case KSPROPERTY_PIN_NECESSARYINSTANCES
:
616 Status
= KspHandleNecessaryPropertyInstances(&Irp
->IoStatus
, Request
, Data
, This
);
619 case KSPROPERTY_PIN_DATAINTERSECTION
:
620 Status
= KspHandleDataIntersection(Irp
, &Irp
->IoStatus
, Request
, Data
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
, This
);
622 case KSPROPERTY_PIN_PHYSICALCONNECTION
:
623 case KSPROPERTY_PIN_CONSTRAINEDDATARANGES
:
625 Status
= STATUS_NOT_IMPLEMENTED
;
629 Status
= STATUS_UNSUCCESSFUL
;
637 IN PIO_STATUS_BLOCK IoStatus
,
638 IN KSPROPERTY_SET
* FilterPropertySet
,
639 IN ULONG FilterPropertySetCount
,
640 IN PKSPROPERTY Property
,
641 IN ULONG InputBufferLength
,
642 IN ULONG OutputBufferLength
,
643 OUT PFNKSHANDLER
*PropertyHandler
)
645 ULONG Index
, ItemIndex
;
647 for(Index
= 0; Index
< FilterPropertySetCount
; Index
++)
649 if (IsEqualGUIDAligned(&Property
->Set
, FilterPropertySet
[Index
].Set
))
651 for(ItemIndex
= 0; ItemIndex
< FilterPropertySet
[Index
].PropertiesCount
; ItemIndex
++)
653 if (FilterPropertySet
[Index
].PropertyItem
[ItemIndex
].PropertyId
== Property
->Id
)
655 if (Property
->Flags
& KSPROPERTY_TYPE_SET
)
656 *PropertyHandler
= FilterPropertySet
[Index
].PropertyItem
[ItemIndex
].SetPropertyHandler
;
658 if (Property
->Flags
& KSPROPERTY_TYPE_GET
)
659 *PropertyHandler
= FilterPropertySet
[Index
].PropertyItem
[ItemIndex
].GetPropertyHandler
;
661 if (FilterPropertySet
[Index
].PropertyItem
[ItemIndex
].MinProperty
> InputBufferLength
)
663 /* too small input buffer */
664 IoStatus
->Information
= FilterPropertySet
[Index
].PropertyItem
[ItemIndex
].MinProperty
;
665 IoStatus
->Status
= STATUS_BUFFER_TOO_SMALL
;
666 return STATUS_BUFFER_TOO_SMALL
;
669 if (FilterPropertySet
[Index
].PropertyItem
[ItemIndex
].MinData
> OutputBufferLength
)
671 /* too small output buffer */
672 IoStatus
->Information
= FilterPropertySet
[Index
].PropertyItem
[ItemIndex
].MinData
;
673 IoStatus
->Status
= STATUS_BUFFER_TOO_SMALL
;
674 return STATUS_BUFFER_TOO_SMALL
;
676 return STATUS_SUCCESS
;
681 return STATUS_UNSUCCESSFUL
;
688 IKsFilter_DispatchDeviceIoControl(
689 IN PDEVICE_OBJECT DeviceObject
,
692 PIO_STACK_LOCATION IoStack
;
693 PFNKSHANDLER PropertyHandler
= NULL
;
695 IKsFilterImpl
* This
;
698 /* obtain filter from object header */
699 Status
= IKsFilter_GetFilterFromIrp(Irp
, &Filter
);
700 if (!NT_SUCCESS(Status
))
703 /* get our real implementation */
704 This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, lpVtbl
);
706 /* current irp stack */
707 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
709 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
!= IOCTL_KS_PROPERTY
)
713 /* release filter interface */
714 Filter
->lpVtbl
->Release(Filter
);
716 /* complete and forget irp */
717 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
718 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
719 return STATUS_NOT_IMPLEMENTED
;
722 /* find a supported property handler */
723 Status
= FindPropertyHandler(&Irp
->IoStatus
, FilterPropertySet
, 2, IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
, IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
, &PropertyHandler
);
724 if (NT_SUCCESS(Status
))
726 KSPROPERTY_ITEM_IRP_STORAGE(Irp
) = (PVOID
)This
;
727 DPRINT("Calling property handler %p\n", PropertyHandler
);
728 Status
= PropertyHandler(Irp
, IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
, Irp
->UserBuffer
);
732 /* call driver's property handler */
734 Status
= STATUS_NOT_IMPLEMENTED
;
737 Irp
->IoStatus
.Status
= Status
;
738 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
744 static KSDISPATCH_TABLE DispatchTable
=
746 IKsFilter_DispatchDeviceIoControl
,
747 KsDispatchInvalidDeviceRequest
,
748 KsDispatchInvalidDeviceRequest
,
749 KsDispatchInvalidDeviceRequest
,
750 IKsFilter_DispatchClose
,
751 KsDispatchQuerySecurity
,
752 KsDispatchSetSecurity
,
753 KsDispatchFastIoDeviceControlFailure
,
754 KsDispatchFastReadFailure
,
755 KsDispatchFastReadFailure
,
760 IKsFilter_CreateDescriptors(
761 IKsFilterImpl
* This
,
762 KSFILTER_DESCRIPTOR
* FilterDescriptor
)
766 /* initialize pin descriptors */
767 if (FilterDescriptor
->PinDescriptorsCount
)
769 /* allocate pin instance count array */
770 This
->PinInstanceCount
= AllocateItem(NonPagedPool
, sizeof(ULONG
) * FilterDescriptor
->PinDescriptorsCount
);
771 if(!This
->PinDescriptors
)
773 return STATUS_INSUFFICIENT_RESOURCES
;
776 /* allocate pin descriptor array */
777 This
->PinDescriptors
= AllocateItem(NonPagedPool
, sizeof(KSPIN_DESCRIPTOR
) * FilterDescriptor
->PinDescriptorsCount
);
778 if(!This
->PinDescriptors
)
780 FreeItem(This
->PinInstanceCount
);
781 return STATUS_INSUFFICIENT_RESOURCES
;
785 This
->PinDescriptorCount
= FilterDescriptor
->PinDescriptorsCount
;
786 /* now copy those pin descriptors over */
787 for(Index
= 0; Index
< FilterDescriptor
->PinDescriptorsCount
; Index
++)
789 /* copy one pin per time */
790 RtlMoveMemory(&This
->PinDescriptors
[Index
], &FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
, sizeof(KSPIN_DESCRIPTOR
));
794 /* initialize topology descriptor */
795 This
->Topology
.CategoriesCount
= FilterDescriptor
->CategoriesCount
;
796 This
->Topology
.Categories
= FilterDescriptor
->Categories
;
797 This
->Topology
.TopologyNodesCount
= FilterDescriptor
->NodeDescriptorsCount
;
798 This
->Topology
.TopologyConnectionsCount
= FilterDescriptor
->ConnectionsCount
;
799 This
->Topology
.TopologyConnections
= FilterDescriptor
->Connections
;
801 if (This
->Topology
.TopologyNodesCount
> 0)
803 This
->Topology
.TopologyNodes
= AllocateItem(NonPagedPool
, sizeof(GUID
) * This
->Topology
.TopologyNodesCount
);
804 /* allocate topology node types array */
805 if (!This
->Topology
.TopologyNodes
)
806 return STATUS_INSUFFICIENT_RESOURCES
;
808 This
->Topology
.TopologyNodesNames
= AllocateItem(NonPagedPool
, sizeof(GUID
) * This
->Topology
.TopologyNodesCount
);
809 /* allocate topology names array */
810 if (!This
->Topology
.TopologyNodesNames
)
812 FreeItem((PVOID
)This
->Topology
.TopologyNodes
);
813 return STATUS_INSUFFICIENT_RESOURCES
;
816 for(Index
= 0; Index
< This
->Topology
.TopologyNodesCount
; Index
++)
818 /* copy topology type */
819 RtlMoveMemory((PVOID
)&This
->Topology
.TopologyNodes
[Index
], FilterDescriptor
->NodeDescriptors
[Index
].Type
, sizeof(GUID
));
820 /* copy topology name */
821 RtlMoveMemory((PVOID
)&This
->Topology
.TopologyNodesNames
[Index
], FilterDescriptor
->NodeDescriptors
[Index
].Name
, sizeof(GUID
));
826 return STATUS_SUCCESS
;
830 IKsFilter_CopyFilterDescriptor(
831 IKsFilterImpl
* This
,
832 const KSFILTER_DESCRIPTOR
* FilterDescriptor
)
834 This
->Filter
.Descriptor
= (const KSFILTER_DESCRIPTOR
*)AllocateItem(NonPagedPool
, sizeof(KSFILTER_DESCRIPTOR
));
835 if (!This
->Filter
.Descriptor
)
836 return STATUS_INSUFFICIENT_RESOURCES
;
838 /* copy all fields */
839 RtlMoveMemory((PVOID
)This
->Filter
.Descriptor
, FilterDescriptor
, sizeof(KSFILTER_DESCRIPTOR
));
842 /* perform deep copy of pin descriptors */
843 if (FilterDescriptor
->PinDescriptorsCount
)
845 KSPIN_DESCRIPTOR_EX
* PinDescriptors
= (KSPIN_DESCRIPTOR_EX
*)AllocateItem(NonPagedPool
, FilterDescriptor
->PinDescriptorSize
* FilterDescriptor
->PinDescriptorsCount
);
850 FreeItem((PVOID
)This
->Filter
.Descriptor
);
851 return STATUS_INSUFFICIENT_RESOURCES
;
853 RtlMoveMemory((PVOID
)PinDescriptors
, FilterDescriptor
->PinDescriptors
, FilterDescriptor
->PinDescriptorSize
* FilterDescriptor
->PinDescriptorsCount
);
855 /* brain-dead gcc hack */
856 RtlMoveMemory((PVOID
)&This
->Filter
.Descriptor
->PinDescriptors
, PinDescriptors
, sizeof(PKSPIN_DESCRIPTOR_EX
));
860 /* perform deep copy of node descriptors */
861 if (FilterDescriptor
->NodeDescriptorsCount
)
863 KSNODE_DESCRIPTOR
* NodeDescriptor
= AllocateItem(NonPagedPool
, FilterDescriptor
->NodeDescriptorsCount
* FilterDescriptor
->NodeDescriptorSize
);
866 if (This
->Filter
.Descriptor
->PinDescriptors
)
867 FreeItem((PVOID
)This
->Filter
.Descriptor
->PinDescriptors
);
868 FreeItem((PVOID
)This
->Filter
.Descriptor
);
869 return STATUS_INSUFFICIENT_RESOURCES
;
871 RtlMoveMemory((PVOID
)NodeDescriptor
, FilterDescriptor
->NodeDescriptors
, FilterDescriptor
->NodeDescriptorsCount
* FilterDescriptor
->NodeDescriptorSize
);
873 /* brain-dead gcc hack */
874 RtlMoveMemory((PVOID
)&This
->Filter
.Descriptor
->NodeDescriptors
, NodeDescriptor
, sizeof(PKSNODE_DESCRIPTOR
));
877 /* perform deep copy of connections descriptors */
878 if (FilterDescriptor
->NodeDescriptorsCount
)
880 KSTOPOLOGY_CONNECTION
* Connections
= AllocateItem(NonPagedPool
, sizeof(KSTOPOLOGY_CONNECTION
) * FilterDescriptor
->ConnectionsCount
);
883 if (This
->Filter
.Descriptor
->PinDescriptors
)
884 FreeItem((PVOID
)This
->Filter
.Descriptor
->PinDescriptors
);
886 if (This
->Filter
.Descriptor
->NodeDescriptors
)
887 FreeItem((PVOID
)This
->Filter
.Descriptor
->PinDescriptors
);
889 FreeItem((PVOID
)This
->Filter
.Descriptor
);
890 return STATUS_INSUFFICIENT_RESOURCES
;
893 RtlMoveMemory((PVOID
)Connections
, FilterDescriptor
->Connections
, sizeof(KSTOPOLOGY_CONNECTION
) * FilterDescriptor
->ConnectionsCount
);
895 /* brain-dead gcc hack */
896 RtlMoveMemory((PVOID
)&This
->Filter
.Descriptor
->Connections
, Connections
, sizeof(PKSTOPOLOGY_CONNECTION
));
899 return STATUS_SUCCESS
;
906 IN PDEVICE_OBJECT DeviceObject
,
908 IN IKsFilterFactory
*iface
)
910 IKsFilterImpl
* This
;
912 PKSFILTERFACTORY Factory
;
913 PIO_STACK_LOCATION IoStack
;
914 PDEVICE_EXTENSION DeviceExtension
;
917 /* get device extension */
918 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
920 /* get the filter factory */
921 Factory
= iface
->lpVtbl
->GetStruct(iface
);
923 if (!Factory
|| !Factory
->FilterDescriptor
|| !Factory
->FilterDescriptor
->Dispatch
|| !Factory
->FilterDescriptor
->Dispatch
->Create
)
925 /* Sorry it just will not work */
926 return STATUS_UNSUCCESSFUL
;
929 /* allocate filter instance */
930 This
= AllocateItem(NonPagedPool
, sizeof(IKsFilterFactory
));
932 return STATUS_INSUFFICIENT_RESOURCES
;
934 /* copy filter descriptor */
935 Status
= IKsFilter_CopyFilterDescriptor(This
, Factory
->FilterDescriptor
);
936 if (!NT_SUCCESS(Status
))
938 /* not enough memory */
940 return STATUS_INSUFFICIENT_RESOURCES
;
943 /* get current irp stack */
944 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
947 /* initialize object bag */
948 This
->Filter
.Bag
= AllocateItem(NonPagedPool
, sizeof(KSIOBJECT_BAG
));
949 if (!This
->Filter
.Bag
)
953 return STATUS_INSUFFICIENT_RESOURCES
;
958 KsDevice
= (IKsDevice
*)&DeviceExtension
->DeviceHeader
->lpVtblIKsDevice
;
959 KsDevice
->lpVtbl
->InitializeObjectBag(KsDevice
, (PKSIOBJECT_BAG
)This
->Filter
.Bag
, NULL
);
961 /* initialize filter instance */
963 This
->lpVtbl
= &vt_IKsFilter
;
964 This
->lpVtblKsControl
= &vt_IKsControl
;
966 This
->Filter
.Descriptor
= Factory
->FilterDescriptor
;
967 This
->Factory
= Factory
;
968 This
->FilterFactory
= iface
;
969 This
->FileObject
= IoStack
->FileObject
;
970 This
->Header
.KsDevice
= &DeviceExtension
->DeviceHeader
->KsDevice
;
971 This
->Header
.Parent
.KsFilterFactory
= iface
->lpVtbl
->GetStruct(iface
);
972 This
->Header
.Type
= KsObjectTypeFilter
;
973 KeInitializeMutex(&This
->ProcessingMutex
, 0);
976 /* allocate the stream descriptors */
977 Status
= IKsFilter_CreateDescriptors(This
, (PKSFILTER_DESCRIPTOR
)Factory
->FilterDescriptor
);
978 if (!NT_SUCCESS(Status
))
980 /* what can go wrong, goes wrong */
985 /* now add the filter instance to the filter factory */
986 Status
= iface
->lpVtbl
->AddFilterInstance(iface
, (IKsFilter
*)&This
->lpVtbl
);
988 if (!NT_SUCCESS(Status
))
990 /* failed to add filter */
996 /* now let driver initialize the filter instance */
997 Status
= Factory
->FilterDescriptor
->Dispatch
->Create(&This
->Filter
, Irp
);
999 if (!NT_SUCCESS(Status
) && Status
!= STATUS_PENDING
)
1001 /* driver failed to initialize */
1002 DPRINT1("Driver: Status %x\n", Status
);
1004 /* remove filter instance from filter factory */
1005 iface
->lpVtbl
->RemoveFilterInstance(iface
, (IKsFilter
*)&This
->lpVtbl
);
1007 /* free filter instance */
1013 /* now allocate the object header */
1014 Status
= KsAllocateObjectHeader((PVOID
*)&This
->ObjectHeader
, 0, NULL
, Irp
, &DispatchTable
);
1015 if (!NT_SUCCESS(Status
))
1017 /* failed to allocate object header */
1018 DPRINT1("Failed to allocate object header %x\n", Status
);
1023 /* initialize object header */
1024 This
->Header
.Type
= KsObjectTypeFilter
;
1025 This
->Header
.KsDevice
= &DeviceExtension
->DeviceHeader
->KsDevice
;
1026 This
->ObjectHeader
->Type
= KsObjectTypeFilter
;
1027 This
->ObjectHeader
->Unknown
= (PUNKNOWN
)&This
->lpVtbl
;
1028 This
->ObjectHeader
->ObjectType
= (PVOID
)&This
->Filter
;
1031 /* completed initialization */
1041 KsFilterAcquireProcessingMutex(
1042 IN PKSFILTER Filter
)
1044 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1046 KeWaitForSingleObject(&This
->ProcessingMutex
, Executive
, KernelMode
, FALSE
, NULL
);
1055 KsFilterReleaseProcessingMutex(
1056 IN PKSFILTER Filter
)
1058 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1060 KeReleaseMutex(&This
->ProcessingMutex
, FALSE
);
1069 KsFilterAddTopologyConnections (
1070 IN PKSFILTER Filter
,
1071 IN ULONG NewConnectionsCount
,
1072 IN
const KSTOPOLOGY_CONNECTION
*const NewTopologyConnections
)
1075 KSTOPOLOGY_CONNECTION
* Connections
;
1076 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1078 Count
= This
->Filter
.Descriptor
->ConnectionsCount
+ NewConnectionsCount
;
1080 /* allocate array */
1081 Connections
= AllocateItem(NonPagedPool
, Count
* sizeof(KSTOPOLOGY_CONNECTION
));
1083 return STATUS_INSUFFICIENT_RESOURCES
;
1085 /* FIXME verify connections */
1087 if (This
->Filter
.Descriptor
->ConnectionsCount
)
1089 /* copy old connections */
1090 RtlMoveMemory(Connections
, This
->Filter
.Descriptor
->Connections
, sizeof(KSTOPOLOGY_CONNECTION
) * This
->Filter
.Descriptor
->ConnectionsCount
);
1093 /* add new connections */
1094 RtlMoveMemory((PVOID
)(Connections
+ This
->Filter
.Descriptor
->ConnectionsCount
), NewTopologyConnections
, NewConnectionsCount
);
1096 /* add the new connections */
1097 RtlMoveMemory((PVOID
)&This
->Filter
.Descriptor
->ConnectionsCount
, &Count
, sizeof(ULONG
)); /* brain-dead gcc hack */
1099 /* free old connections array */
1100 if (This
->Filter
.Descriptor
->ConnectionsCount
)
1102 FreeItem((PVOID
)This
->Filter
.Descriptor
->Connections
);
1105 /* brain-dead gcc hack */
1106 RtlMoveMemory((PVOID
)&This
->Filter
.Descriptor
->Connections
, Connections
, sizeof(KSTOPOLOGY_CONNECTION
*));
1108 return STATUS_SUCCESS
;
1117 KsFilterAttemptProcessing(
1118 IN PKSFILTER Filter
,
1119 IN BOOLEAN Asynchronous
)
1130 KsFilterCreateNode (
1131 IN PKSFILTER Filter
,
1132 IN
const KSNODE_DESCRIPTOR
*const NodeDescriptor
,
1136 return STATUS_NOT_IMPLEMENTED
;
1145 KsFilterCreatePinFactory (
1146 IN PKSFILTER Filter
,
1147 IN
const KSPIN_DESCRIPTOR_EX
*const InPinDescriptor
,
1151 ULONG
*PinInstanceCount
;
1152 KSPIN_DESCRIPTOR_EX
* PinDescriptorsEx
;
1153 KSPIN_DESCRIPTOR
* PinDescriptors
;
1154 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1156 /* calculate existing count */
1157 Count
= This
->PinDescriptorCount
+ 1;
1159 /* allocate pin descriptors array */
1160 PinDescriptorsEx
= AllocateItem(NonPagedPool
, max(This
->Filter
.Descriptor
->PinDescriptorSize
, sizeof(KSPIN_DESCRIPTOR_EX
)) * Count
);
1161 if (!PinDescriptorsEx
)
1162 return STATUS_INSUFFICIENT_RESOURCES
;
1164 /* allocate pin instance count array */
1165 PinInstanceCount
= AllocateItem(NonPagedPool
, sizeof(ULONG
) * Count
);
1166 if (!PinInstanceCount
)
1168 /* not enough memory */
1169 FreeItem(PinDescriptorsEx
);
1170 return STATUS_INSUFFICIENT_RESOURCES
;
1173 /* allocate pin descriptor array for pin property handling */
1174 PinDescriptors
= AllocateItem(NonPagedPool
, sizeof(KSPIN_DESCRIPTOR
) * Count
);
1175 if (!PinDescriptors
)
1177 /* not enough memory */
1178 FreeItem(PinDescriptorsEx
);
1179 FreeItem(PinInstanceCount
);
1180 return STATUS_INSUFFICIENT_RESOURCES
;
1183 /* now copy all fields */
1186 /* copy old descriptors */
1187 RtlMoveMemory(PinDescriptorsEx
, This
->Filter
.Descriptor
->PinDescriptors
, max(This
->Filter
.Descriptor
->PinDescriptorSize
, sizeof(KSPIN_DESCRIPTOR_EX
)) * This
->PinDescriptorCount
);
1188 RtlMoveMemory(PinInstanceCount
, This
->PinInstanceCount
, This
->PinDescriptorCount
* sizeof(ULONG
));
1189 RtlMoveMemory(PinDescriptors
, This
->PinDescriptors
, sizeof(KSPIN_DESCRIPTOR
) * This
->PinDescriptorCount
);
1191 /* now free old descriptors */
1192 FreeItem(This
->PinInstanceCount
);
1193 FreeItem((PVOID
)This
->Filter
.Descriptor
->PinDescriptors
);
1194 FreeItem(This
->PinDescriptors
);
1197 /* add new pin factory */
1198 RtlMoveMemory((PVOID
)((ULONG_PTR
)PinDescriptorsEx
+ max(This
->Filter
.Descriptor
->PinDescriptorSize
, sizeof(KSPIN_DESCRIPTOR_EX
)) * This
->PinDescriptorCount
), InPinDescriptor
, sizeof(KSPIN_DESCRIPTOR
));
1199 RtlMoveMemory((PVOID
)(PinDescriptors
+ This
->PinDescriptorCount
), &InPinDescriptor
->PinDescriptor
, sizeof(KSPIN_DESCRIPTOR
));
1201 /* replace old descriptor by using a gcc-compliant hack */
1202 RtlMoveMemory((PVOID
)&This
->Filter
.Descriptor
->PinDescriptors
, PinDescriptorsEx
, sizeof(KSPIN_DESCRIPTOR_EX
*));
1203 RtlMoveMemory((PVOID
)&This
->Filter
.Descriptor
->PinDescriptorsCount
, &Count
, sizeof(ULONG
));
1205 This
->PinDescriptors
= PinDescriptors
;
1206 This
->PinInstanceCount
= PinInstanceCount
;
1208 /* store new pin id */
1209 *PinID
= This
->PinDescriptorCount
;
1211 /* increment pin descriptor count */
1212 This
->PinDescriptorCount
++;
1214 return STATUS_SUCCESS
;
1225 IN PKSFILTER Filter
)
1237 KsFilterGetChildPinCount(
1238 IN PKSFILTER Filter
,
1241 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1243 if (PinId
>= This
->PinDescriptorCount
)
1245 /* index is out of bounds */
1248 /* return pin instance count */
1249 return This
->PinInstanceCount
[PinId
];
1258 KsFilterGetFirstChildPin(
1259 IN PKSFILTER Filter
,
1272 KsFilterRegisterPowerCallbacks(
1273 IN PKSFILTER Filter
,
1274 IN PFNKSFILTERPOWER Sleep OPTIONAL
,
1275 IN PFNKSFILTERPOWER Wake OPTIONAL
)
1277 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1279 This
->Sleep
= Sleep
;
1292 PIO_STACK_LOCATION IoStack
;
1293 PKSIOBJECT_HEADER ObjectHeader
;
1295 /* get current irp stack location */
1296 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1299 ASSERT(IoStack
->FileObject
);
1301 /* get object header */
1302 ObjectHeader
= (PKSIOBJECT_HEADER
)IoStack
->FileObject
->FsContext
;
1304 if (ObjectHeader
->Type
== KsObjectTypeFilter
)
1306 /* irp is targeted at the filter */
1307 return (PKSFILTER
)ObjectHeader
->ObjectType
;
1309 else if (ObjectHeader
->Type
== KsObjectTypePin
)
1311 /* irp is for a pin */
1312 return KsPinGetParentFilter((PKSPIN
)ObjectHeader
->ObjectType
);
1316 /* irp is unappropiate to retrieve a filter */