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 (NT_SUCCESS(Status
) && 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 /* free object header */
444 KsFreeObjectHeader(This
->ObjectHeader
);
448 /* complete and forget */
449 Irp
->IoStatus
.Status
= Status
;
451 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
459 KspHandlePropertyInstances(
460 IN PIO_STATUS_BLOCK IoStatus
,
461 IN PKSIDENTIFIER Request
,
463 IN IKsFilterImpl
* This
,
466 KSPIN_CINSTANCES
* Instances
;
467 KSP_PIN
* Pin
= (KSP_PIN
*)Request
;
469 if (!This
->Factory
->FilterDescriptor
|| !This
->Factory
->FilterDescriptor
->PinDescriptorsCount
)
471 /* no filter / pin descriptor */
472 IoStatus
->Status
= STATUS_NOT_IMPLEMENTED
;
473 return STATUS_NOT_IMPLEMENTED
;
476 /* ignore custom structs for now */
477 ASSERT(This
->Factory
->FilterDescriptor
->PinDescriptorSize
== sizeof(KSPIN_DESCRIPTOR_EX
));
478 ASSERT(This
->Factory
->FilterDescriptor
->PinDescriptorsCount
> Pin
->PinId
);
480 Instances
= (KSPIN_CINSTANCES
*)Data
;
481 /* max instance count */
482 Instances
->PossibleCount
= This
->Factory
->FilterDescriptor
->PinDescriptors
[Pin
->PinId
].InstancesPossible
;
483 /* current instance count */
484 Instances
->CurrentCount
= This
->PinInstanceCount
[Pin
->PinId
];
486 IoStatus
->Information
= sizeof(KSPIN_CINSTANCES
);
487 IoStatus
->Status
= STATUS_SUCCESS
;
488 return STATUS_SUCCESS
;
492 KspHandleNecessaryPropertyInstances(
493 IN PIO_STATUS_BLOCK IoStatus
,
494 IN PKSIDENTIFIER Request
,
496 IN IKsFilterImpl
* This
)
499 KSP_PIN
* Pin
= (KSP_PIN
*)Request
;
501 if (!This
->Factory
->FilterDescriptor
|| !This
->Factory
->FilterDescriptor
->PinDescriptorsCount
)
503 /* no filter / pin descriptor */
504 IoStatus
->Status
= STATUS_NOT_IMPLEMENTED
;
505 return STATUS_NOT_IMPLEMENTED
;
508 /* ignore custom structs for now */
509 ASSERT(This
->Factory
->FilterDescriptor
->PinDescriptorSize
== sizeof(KSPIN_DESCRIPTOR_EX
));
510 ASSERT(This
->Factory
->FilterDescriptor
->PinDescriptorsCount
> Pin
->PinId
);
512 Result
= (PULONG
)Data
;
513 *Result
= This
->Factory
->FilterDescriptor
->PinDescriptors
[Pin
->PinId
].InstancesNecessary
;
515 IoStatus
->Information
= sizeof(ULONG
);
516 IoStatus
->Status
= STATUS_SUCCESS
;
517 return STATUS_SUCCESS
;
521 KspHandleDataIntersection(
523 IN PIO_STATUS_BLOCK IoStatus
,
524 IN PKSIDENTIFIER Request
,
527 IN IKsFilterImpl
* This
)
529 PKSMULTIPLE_ITEM MultipleItem
;
530 PKSDATARANGE DataRange
;
531 NTSTATUS Status
= STATUS_NO_MATCH
;
533 KSP_PIN
* Pin
= (KSP_PIN
*)Request
;
535 /* Access parameters */
536 MultipleItem
= (PKSMULTIPLE_ITEM
)(Pin
+ 1);
537 DataRange
= (PKSDATARANGE
)(MultipleItem
+ 1);
539 if (!This
->Factory
->FilterDescriptor
|| !This
->Factory
->FilterDescriptor
->PinDescriptorsCount
)
541 /* no filter / pin descriptor */
542 IoStatus
->Status
= STATUS_NOT_IMPLEMENTED
;
543 return STATUS_NOT_IMPLEMENTED
;
546 /* ignore custom structs for now */
547 ASSERT(This
->Factory
->FilterDescriptor
->PinDescriptorSize
== sizeof(KSPIN_DESCRIPTOR_EX
));
548 ASSERT(This
->Factory
->FilterDescriptor
->PinDescriptorsCount
> Pin
->PinId
);
550 if (This
->Factory
->FilterDescriptor
->PinDescriptors
[Pin
->PinId
].IntersectHandler
== NULL
||
551 This
->Factory
->FilterDescriptor
->PinDescriptors
[Pin
->PinId
].PinDescriptor
.DataRanges
== NULL
||
552 This
->Factory
->FilterDescriptor
->PinDescriptors
[Pin
->PinId
].PinDescriptor
.DataRangesCount
== 0)
554 /* no driver supported intersect handler / no provided data ranges */
555 IoStatus
->Status
= STATUS_NOT_IMPLEMENTED
;
556 return STATUS_NOT_IMPLEMENTED
;
559 for(Index
= 0; Index
< MultipleItem
->Count
; Index
++)
561 /* Call miniport's properitary handler */
562 Status
= This
->Factory
->FilterDescriptor
->PinDescriptors
[Pin
->PinId
].IntersectHandler(NULL
, /* context */
566 (PKSDATAFORMAT
)This
->Factory
->FilterDescriptor
->PinDescriptors
[Pin
->PinId
].PinDescriptor
.DataRanges
,
571 if (Status
== STATUS_SUCCESS
)
573 IoStatus
->Information
= Length
;
576 DataRange
= UlongToPtr(PtrToUlong(DataRange
) + DataRange
->FormatSize
);
579 IoStatus
->Status
= Status
;
585 KspPinPropertyHandler(
587 IN PKSIDENTIFIER Request
,
590 PIO_STACK_LOCATION IoStack
;
591 IKsFilterImpl
* This
;
592 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
594 /* get filter implementation */
595 This
= (IKsFilterImpl
*)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
597 /* get current stack location */
598 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
602 case KSPROPERTY_PIN_CTYPES
:
603 case KSPROPERTY_PIN_DATAFLOW
:
604 case KSPROPERTY_PIN_DATARANGES
:
605 case KSPROPERTY_PIN_INTERFACES
:
606 case KSPROPERTY_PIN_MEDIUMS
:
607 case KSPROPERTY_PIN_COMMUNICATION
:
608 case KSPROPERTY_PIN_CATEGORY
:
609 case KSPROPERTY_PIN_NAME
:
610 case KSPROPERTY_PIN_PROPOSEDATAFORMAT
:
611 Status
= KsPinPropertyHandler(Irp
, Request
, Data
, This
->PinDescriptorCount
, This
->PinDescriptors
);
613 case KSPROPERTY_PIN_GLOBALCINSTANCES
:
614 Status
= KspHandlePropertyInstances(&Irp
->IoStatus
, Request
, Data
, This
, TRUE
);
616 case KSPROPERTY_PIN_CINSTANCES
:
617 Status
= KspHandlePropertyInstances(&Irp
->IoStatus
, Request
, Data
, This
, FALSE
);
619 case KSPROPERTY_PIN_NECESSARYINSTANCES
:
620 Status
= KspHandleNecessaryPropertyInstances(&Irp
->IoStatus
, Request
, Data
, This
);
623 case KSPROPERTY_PIN_DATAINTERSECTION
:
624 Status
= KspHandleDataIntersection(Irp
, &Irp
->IoStatus
, Request
, Data
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
, This
);
626 case KSPROPERTY_PIN_PHYSICALCONNECTION
:
627 case KSPROPERTY_PIN_CONSTRAINEDDATARANGES
:
629 Status
= STATUS_NOT_IMPLEMENTED
;
633 Status
= STATUS_UNSUCCESSFUL
;
641 IKsFilter_DispatchDeviceIoControl(
642 IN PDEVICE_OBJECT DeviceObject
,
645 PIO_STACK_LOCATION IoStack
;
646 PFNKSHANDLER PropertyHandler
= NULL
;
648 IKsFilterImpl
* This
;
651 /* obtain filter from object header */
652 Status
= IKsFilter_GetFilterFromIrp(Irp
, &Filter
);
653 if (!NT_SUCCESS(Status
))
656 /* get our real implementation */
657 This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, lpVtbl
);
659 /* current irp stack */
660 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
662 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
!= IOCTL_KS_PROPERTY
)
666 /* release filter interface */
667 Filter
->lpVtbl
->Release(Filter
);
669 /* complete and forget irp */
670 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
671 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
672 return STATUS_NOT_IMPLEMENTED
;
675 /* find a supported property handler */
676 Status
= KsPropertyHandler(Irp
, 2, FilterPropertySet
);
677 if (NT_SUCCESS(Status
))
679 KSPROPERTY_ITEM_IRP_STORAGE(Irp
) = (PVOID
)This
;
680 DPRINT("Calling property handler %p\n", PropertyHandler
);
681 Status
= PropertyHandler(Irp
, IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
, Irp
->UserBuffer
);
685 /* call driver's property handler */
687 Status
= STATUS_NOT_IMPLEMENTED
;
690 Irp
->IoStatus
.Status
= Status
;
691 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
697 static KSDISPATCH_TABLE DispatchTable
=
699 IKsFilter_DispatchDeviceIoControl
,
700 KsDispatchInvalidDeviceRequest
,
701 KsDispatchInvalidDeviceRequest
,
702 KsDispatchInvalidDeviceRequest
,
703 IKsFilter_DispatchClose
,
704 KsDispatchQuerySecurity
,
705 KsDispatchSetSecurity
,
706 KsDispatchFastIoDeviceControlFailure
,
707 KsDispatchFastReadFailure
,
708 KsDispatchFastReadFailure
,
713 IKsFilter_CreateDescriptors(
714 IKsFilterImpl
* This
,
715 KSFILTER_DESCRIPTOR
* FilterDescriptor
)
719 /* initialize pin descriptors */
720 if (FilterDescriptor
->PinDescriptorsCount
)
722 /* allocate pin instance count array */
723 This
->PinInstanceCount
= AllocateItem(NonPagedPool
, sizeof(ULONG
) * FilterDescriptor
->PinDescriptorsCount
);
724 if(!This
->PinDescriptors
)
726 return STATUS_INSUFFICIENT_RESOURCES
;
729 /* allocate pin descriptor array */
730 This
->PinDescriptors
= AllocateItem(NonPagedPool
, sizeof(KSPIN_DESCRIPTOR
) * FilterDescriptor
->PinDescriptorsCount
);
731 if(!This
->PinDescriptors
)
733 FreeItem(This
->PinInstanceCount
);
734 return STATUS_INSUFFICIENT_RESOURCES
;
738 This
->PinDescriptorCount
= FilterDescriptor
->PinDescriptorsCount
;
739 /* now copy those pin descriptors over */
740 for(Index
= 0; Index
< FilterDescriptor
->PinDescriptorsCount
; Index
++)
742 /* copy one pin per time */
743 RtlMoveMemory(&This
->PinDescriptors
[Index
], &FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
, sizeof(KSPIN_DESCRIPTOR
));
747 /* initialize topology descriptor */
748 This
->Topology
.CategoriesCount
= FilterDescriptor
->CategoriesCount
;
749 This
->Topology
.Categories
= FilterDescriptor
->Categories
;
750 This
->Topology
.TopologyNodesCount
= FilterDescriptor
->NodeDescriptorsCount
;
751 This
->Topology
.TopologyConnectionsCount
= FilterDescriptor
->ConnectionsCount
;
752 This
->Topology
.TopologyConnections
= FilterDescriptor
->Connections
;
754 if (This
->Topology
.TopologyNodesCount
> 0)
756 This
->Topology
.TopologyNodes
= AllocateItem(NonPagedPool
, sizeof(GUID
) * This
->Topology
.TopologyNodesCount
);
757 /* allocate topology node types array */
758 if (!This
->Topology
.TopologyNodes
)
759 return STATUS_INSUFFICIENT_RESOURCES
;
761 This
->Topology
.TopologyNodesNames
= AllocateItem(NonPagedPool
, sizeof(GUID
) * This
->Topology
.TopologyNodesCount
);
762 /* allocate topology names array */
763 if (!This
->Topology
.TopologyNodesNames
)
765 FreeItem((PVOID
)This
->Topology
.TopologyNodes
);
766 return STATUS_INSUFFICIENT_RESOURCES
;
769 for(Index
= 0; Index
< This
->Topology
.TopologyNodesCount
; Index
++)
771 /* copy topology type */
772 RtlMoveMemory((PVOID
)&This
->Topology
.TopologyNodes
[Index
], FilterDescriptor
->NodeDescriptors
[Index
].Type
, sizeof(GUID
));
773 /* copy topology name */
774 RtlMoveMemory((PVOID
)&This
->Topology
.TopologyNodesNames
[Index
], FilterDescriptor
->NodeDescriptors
[Index
].Name
, sizeof(GUID
));
779 return STATUS_SUCCESS
;
783 IKsFilter_CopyFilterDescriptor(
784 IKsFilterImpl
* This
,
785 const KSFILTER_DESCRIPTOR
* FilterDescriptor
)
787 This
->Filter
.Descriptor
= (const KSFILTER_DESCRIPTOR
*)AllocateItem(NonPagedPool
, sizeof(KSFILTER_DESCRIPTOR
));
788 if (!This
->Filter
.Descriptor
)
789 return STATUS_INSUFFICIENT_RESOURCES
;
791 /* copy all fields */
792 RtlMoveMemory((PVOID
)This
->Filter
.Descriptor
, FilterDescriptor
, sizeof(KSFILTER_DESCRIPTOR
));
795 /* perform deep copy of pin descriptors */
796 if (FilterDescriptor
->PinDescriptorsCount
)
798 KSPIN_DESCRIPTOR_EX
* PinDescriptors
= (KSPIN_DESCRIPTOR_EX
*)AllocateItem(NonPagedPool
, FilterDescriptor
->PinDescriptorSize
* FilterDescriptor
->PinDescriptorsCount
);
803 FreeItem((PVOID
)This
->Filter
.Descriptor
);
804 return STATUS_INSUFFICIENT_RESOURCES
;
806 RtlMoveMemory((PVOID
)PinDescriptors
, FilterDescriptor
->PinDescriptors
, FilterDescriptor
->PinDescriptorSize
* FilterDescriptor
->PinDescriptorsCount
);
808 /* brain-dead gcc hack */
809 RtlMoveMemory((PVOID
)&This
->Filter
.Descriptor
->PinDescriptors
, PinDescriptors
, sizeof(PKSPIN_DESCRIPTOR_EX
));
813 /* perform deep copy of node descriptors */
814 if (FilterDescriptor
->NodeDescriptorsCount
)
816 KSNODE_DESCRIPTOR
* NodeDescriptor
= AllocateItem(NonPagedPool
, FilterDescriptor
->NodeDescriptorsCount
* FilterDescriptor
->NodeDescriptorSize
);
819 if (This
->Filter
.Descriptor
->PinDescriptors
)
820 FreeItem((PVOID
)This
->Filter
.Descriptor
->PinDescriptors
);
821 FreeItem((PVOID
)This
->Filter
.Descriptor
);
822 return STATUS_INSUFFICIENT_RESOURCES
;
824 RtlMoveMemory((PVOID
)NodeDescriptor
, FilterDescriptor
->NodeDescriptors
, FilterDescriptor
->NodeDescriptorsCount
* FilterDescriptor
->NodeDescriptorSize
);
826 /* brain-dead gcc hack */
827 RtlMoveMemory((PVOID
)&This
->Filter
.Descriptor
->NodeDescriptors
, NodeDescriptor
, sizeof(PKSNODE_DESCRIPTOR
));
830 /* perform deep copy of connections descriptors */
831 if (FilterDescriptor
->NodeDescriptorsCount
)
833 KSTOPOLOGY_CONNECTION
* Connections
= AllocateItem(NonPagedPool
, sizeof(KSTOPOLOGY_CONNECTION
) * FilterDescriptor
->ConnectionsCount
);
836 if (This
->Filter
.Descriptor
->PinDescriptors
)
837 FreeItem((PVOID
)This
->Filter
.Descriptor
->PinDescriptors
);
839 if (This
->Filter
.Descriptor
->NodeDescriptors
)
840 FreeItem((PVOID
)This
->Filter
.Descriptor
->PinDescriptors
);
842 FreeItem((PVOID
)This
->Filter
.Descriptor
);
843 return STATUS_INSUFFICIENT_RESOURCES
;
846 RtlMoveMemory((PVOID
)Connections
, FilterDescriptor
->Connections
, sizeof(KSTOPOLOGY_CONNECTION
) * FilterDescriptor
->ConnectionsCount
);
848 /* brain-dead gcc hack */
849 RtlMoveMemory((PVOID
)&This
->Filter
.Descriptor
->Connections
, Connections
, sizeof(PKSTOPOLOGY_CONNECTION
));
852 return STATUS_SUCCESS
;
857 IKsFilter_DispatchCreatePin(
858 IN PDEVICE_OBJECT DeviceObject
,
861 IKsFilterImpl
* This
;
862 PKSOBJECT_CREATE_ITEM CreateItem
;
863 PKSPIN_CONNECT Connect
;
866 /* get the create item */
867 CreateItem
= KSCREATE_ITEM_IRP_STORAGE(Irp
);
869 /* get the filter object */
870 This
= (IKsFilterImpl
*)CreateItem
->Context
;
872 /* acquire control mutex */
873 KeWaitForSingleObject(&This
->Header
.ControlMutex
, Executive
, KernelMode
, FALSE
, NULL
);
875 /* now validate the connect request */
876 Status
= KsValidateConnectRequest(Irp
, This
->PinDescriptorCount
, This
->PinDescriptors
, &Connect
);
878 if (NT_SUCCESS(Status
))
880 if (This
->PinInstanceCount
[Connect
->PinId
] < This
->Filter
.Descriptor
->PinDescriptors
[Connect
->PinId
].InstancesPossible
)
883 Status
= KspCreatePin(DeviceObject
, Irp
, This
->Header
.KsDevice
, This
->FilterFactory
, (IKsFilter
*)&This
->lpVtbl
, Connect
, (KSPIN_DESCRIPTOR_EX
*)&This
->Filter
.Descriptor
->PinDescriptors
[Connect
->PinId
]);
885 if (NT_SUCCESS(Status
))
887 /* successfully created pin, increment pin instance count */
888 This
->PinInstanceCount
[Connect
->PinId
]++;
893 /* maximum instance count reached, bye-bye */
894 Status
= STATUS_UNSUCCESSFUL
;
898 /* release control mutex */
899 KeReleaseMutex(&This
->Header
.ControlMutex
, FALSE
);
901 if (Status
!= STATUS_PENDING
)
903 /* complete request */
904 Irp
->IoStatus
.Status
= Status
;
905 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
913 IKsFilter_DispatchCreateNode(
914 IN PDEVICE_OBJECT DeviceObject
,
918 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
919 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
920 return STATUS_UNSUCCESSFUL
;
927 IN PDEVICE_OBJECT DeviceObject
,
929 IN IKsFilterFactory
*iface
)
931 IKsFilterImpl
* This
;
933 PKSFILTERFACTORY Factory
;
934 PIO_STACK_LOCATION IoStack
;
935 PDEVICE_EXTENSION DeviceExtension
;
937 PKSOBJECT_CREATE_ITEM CreateItem
;
939 /* get device extension */
940 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
942 /* get the filter factory */
943 Factory
= iface
->lpVtbl
->GetStruct(iface
);
945 if (!Factory
|| !Factory
->FilterDescriptor
|| !Factory
->FilterDescriptor
->Dispatch
|| !Factory
->FilterDescriptor
->Dispatch
->Create
)
947 /* Sorry it just will not work */
948 return STATUS_UNSUCCESSFUL
;
951 /* allocate filter instance */
952 This
= AllocateItem(NonPagedPool
, sizeof(IKsFilterFactory
));
954 return STATUS_INSUFFICIENT_RESOURCES
;
956 /* copy filter descriptor */
957 Status
= IKsFilter_CopyFilterDescriptor(This
, Factory
->FilterDescriptor
);
958 if (!NT_SUCCESS(Status
))
960 /* not enough memory */
962 return STATUS_INSUFFICIENT_RESOURCES
;
965 /* get current irp stack */
966 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
968 /* initialize object bag */
969 This
->Filter
.Bag
= AllocateItem(NonPagedPool
, sizeof(KSIOBJECT_BAG
));
970 if (!This
->Filter
.Bag
)
974 return STATUS_INSUFFICIENT_RESOURCES
;
977 /* allocate create items */
978 CreateItem
= AllocateItem(NonPagedPool
, sizeof(KSOBJECT_CREATE_ITEM
) * 2);
983 return STATUS_INSUFFICIENT_RESOURCES
;
986 /* initialize pin create item */
987 CreateItem
[0].Create
= IKsFilter_DispatchCreatePin
;
988 CreateItem
[0].Context
= (PVOID
)This
;
989 CreateItem
[0].Flags
= KSCREATE_ITEM_FREEONSTOP
;
990 RtlInitUnicodeString(&CreateItem
[0].ObjectClass
, KSSTRING_Pin
);
991 /* initialize node create item */
992 CreateItem
[1].Create
= IKsFilter_DispatchCreateNode
;
993 CreateItem
[1].Context
= (PVOID
)This
;
994 CreateItem
[1].Flags
= KSCREATE_ITEM_FREEONSTOP
;
995 RtlInitUnicodeString(&CreateItem
[1].ObjectClass
, KSSTRING_TopologyNode
);
998 KsDevice
= (IKsDevice
*)&DeviceExtension
->DeviceHeader
->lpVtblIKsDevice
;
999 KsDevice
->lpVtbl
->InitializeObjectBag(KsDevice
, (PKSIOBJECT_BAG
)This
->Filter
.Bag
, NULL
);
1001 /* initialize filter instance */
1003 This
->lpVtbl
= &vt_IKsFilter
;
1004 This
->lpVtblKsControl
= &vt_IKsControl
;
1006 This
->Filter
.Descriptor
= Factory
->FilterDescriptor
;
1007 This
->Factory
= Factory
;
1008 This
->FilterFactory
= iface
;
1009 This
->FileObject
= IoStack
->FileObject
;
1010 KeInitializeMutex(&This
->ProcessingMutex
, 0);
1011 /* initialize basic header */
1012 This
->Header
.KsDevice
= &DeviceExtension
->DeviceHeader
->KsDevice
;
1013 This
->Header
.Parent
.KsFilterFactory
= iface
->lpVtbl
->GetStruct(iface
);
1014 This
->Header
.Type
= KsObjectTypeFilter
;
1015 KeInitializeMutex(&This
->Header
.ControlMutex
, 0);
1016 InitializeListHead(&This
->Header
.EventList
);
1017 KeInitializeSpinLock(&This
->Header
.EventListLock
);
1023 /* allocate the stream descriptors */
1024 Status
= IKsFilter_CreateDescriptors(This
, (PKSFILTER_DESCRIPTOR
)Factory
->FilterDescriptor
);
1025 if (!NT_SUCCESS(Status
))
1027 /* what can go wrong, goes wrong */
1029 FreeItem(CreateItem
);
1033 /* now add the filter instance to the filter factory */
1034 Status
= iface
->lpVtbl
->AddFilterInstance(iface
, (IKsFilter
*)&This
->lpVtbl
);
1036 if (!NT_SUCCESS(Status
))
1038 /* failed to add filter */
1040 FreeItem(CreateItem
);
1044 /* does the filter have a filter dispatch */
1045 if (Factory
->FilterDescriptor
->Dispatch
)
1047 /* does it have a create routine */
1048 if (Factory
->FilterDescriptor
->Dispatch
->Create
)
1050 /* now let driver initialize the filter instance */
1051 Status
= Factory
->FilterDescriptor
->Dispatch
->Create(&This
->Filter
, Irp
);
1053 if (!NT_SUCCESS(Status
) && Status
!= STATUS_PENDING
)
1055 /* driver failed to initialize */
1056 DPRINT1("Driver: Status %x\n", Status
);
1058 /* remove filter instance from filter factory */
1059 iface
->lpVtbl
->RemoveFilterInstance(iface
, (IKsFilter
*)&This
->lpVtbl
);
1061 /* free filter instance */
1063 FreeItem(CreateItem
);
1069 /* now allocate the object header */
1070 Status
= KsAllocateObjectHeader((PVOID
*)&This
->ObjectHeader
, 2, CreateItem
, Irp
, &DispatchTable
);
1071 if (!NT_SUCCESS(Status
))
1073 /* failed to allocate object header */
1074 DPRINT1("Failed to allocate object header %x\n", Status
);
1079 /* initialize object header extra fields */
1080 This
->ObjectHeader
->Type
= KsObjectTypeFilter
;
1081 This
->ObjectHeader
->Unknown
= (PUNKNOWN
)&This
->lpVtbl
;
1082 This
->ObjectHeader
->ObjectType
= (PVOID
)&This
->Filter
;
1085 /* completed initialization */
1095 KsFilterAcquireProcessingMutex(
1096 IN PKSFILTER Filter
)
1098 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1100 KeWaitForSingleObject(&This
->ProcessingMutex
, Executive
, KernelMode
, FALSE
, NULL
);
1109 KsFilterReleaseProcessingMutex(
1110 IN PKSFILTER Filter
)
1112 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1114 KeReleaseMutex(&This
->ProcessingMutex
, FALSE
);
1123 KsFilterAddTopologyConnections (
1124 IN PKSFILTER Filter
,
1125 IN ULONG NewConnectionsCount
,
1126 IN
const KSTOPOLOGY_CONNECTION
*const NewTopologyConnections
)
1129 KSTOPOLOGY_CONNECTION
* Connections
;
1130 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1132 Count
= This
->Filter
.Descriptor
->ConnectionsCount
+ NewConnectionsCount
;
1134 /* allocate array */
1135 Connections
= AllocateItem(NonPagedPool
, Count
* sizeof(KSTOPOLOGY_CONNECTION
));
1137 return STATUS_INSUFFICIENT_RESOURCES
;
1139 /* FIXME verify connections */
1141 if (This
->Filter
.Descriptor
->ConnectionsCount
)
1143 /* copy old connections */
1144 RtlMoveMemory(Connections
, This
->Filter
.Descriptor
->Connections
, sizeof(KSTOPOLOGY_CONNECTION
) * This
->Filter
.Descriptor
->ConnectionsCount
);
1147 /* add new connections */
1148 RtlMoveMemory((PVOID
)(Connections
+ This
->Filter
.Descriptor
->ConnectionsCount
), NewTopologyConnections
, NewConnectionsCount
);
1150 /* add the new connections */
1151 RtlMoveMemory((PVOID
)&This
->Filter
.Descriptor
->ConnectionsCount
, &Count
, sizeof(ULONG
)); /* brain-dead gcc hack */
1153 /* free old connections array */
1154 if (This
->Filter
.Descriptor
->ConnectionsCount
)
1156 FreeItem((PVOID
)This
->Filter
.Descriptor
->Connections
);
1159 /* brain-dead gcc hack */
1160 RtlMoveMemory((PVOID
)&This
->Filter
.Descriptor
->Connections
, Connections
, sizeof(KSTOPOLOGY_CONNECTION
*));
1162 return STATUS_SUCCESS
;
1171 KsFilterAttemptProcessing(
1172 IN PKSFILTER Filter
,
1173 IN BOOLEAN Asynchronous
)
1184 KsFilterCreateNode (
1185 IN PKSFILTER Filter
,
1186 IN
const KSNODE_DESCRIPTOR
*const NodeDescriptor
,
1190 return STATUS_NOT_IMPLEMENTED
;
1199 KsFilterCreatePinFactory (
1200 IN PKSFILTER Filter
,
1201 IN
const KSPIN_DESCRIPTOR_EX
*const InPinDescriptor
,
1205 ULONG
*PinInstanceCount
;
1206 KSPIN_DESCRIPTOR_EX
* PinDescriptorsEx
;
1207 KSPIN_DESCRIPTOR
* PinDescriptors
;
1208 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1210 /* calculate existing count */
1211 Count
= This
->PinDescriptorCount
+ 1;
1213 /* allocate pin descriptors array */
1214 PinDescriptorsEx
= AllocateItem(NonPagedPool
, max(This
->Filter
.Descriptor
->PinDescriptorSize
, sizeof(KSPIN_DESCRIPTOR_EX
)) * Count
);
1215 if (!PinDescriptorsEx
)
1216 return STATUS_INSUFFICIENT_RESOURCES
;
1218 /* allocate pin instance count array */
1219 PinInstanceCount
= AllocateItem(NonPagedPool
, sizeof(ULONG
) * Count
);
1220 if (!PinInstanceCount
)
1222 /* not enough memory */
1223 FreeItem(PinDescriptorsEx
);
1224 return STATUS_INSUFFICIENT_RESOURCES
;
1227 /* allocate pin descriptor array for pin property handling */
1228 PinDescriptors
= AllocateItem(NonPagedPool
, sizeof(KSPIN_DESCRIPTOR
) * Count
);
1229 if (!PinDescriptors
)
1231 /* not enough memory */
1232 FreeItem(PinDescriptorsEx
);
1233 FreeItem(PinInstanceCount
);
1234 return STATUS_INSUFFICIENT_RESOURCES
;
1237 /* now copy all fields */
1240 /* copy old descriptors */
1241 RtlMoveMemory(PinDescriptorsEx
, This
->Filter
.Descriptor
->PinDescriptors
, max(This
->Filter
.Descriptor
->PinDescriptorSize
, sizeof(KSPIN_DESCRIPTOR_EX
)) * This
->PinDescriptorCount
);
1242 RtlMoveMemory(PinInstanceCount
, This
->PinInstanceCount
, This
->PinDescriptorCount
* sizeof(ULONG
));
1243 RtlMoveMemory(PinDescriptors
, This
->PinDescriptors
, sizeof(KSPIN_DESCRIPTOR
) * This
->PinDescriptorCount
);
1245 /* now free old descriptors */
1246 FreeItem(This
->PinInstanceCount
);
1247 FreeItem((PVOID
)This
->Filter
.Descriptor
->PinDescriptors
);
1248 FreeItem(This
->PinDescriptors
);
1251 /* add new pin factory */
1252 RtlMoveMemory((PVOID
)((ULONG_PTR
)PinDescriptorsEx
+ max(This
->Filter
.Descriptor
->PinDescriptorSize
, sizeof(KSPIN_DESCRIPTOR_EX
)) * This
->PinDescriptorCount
), InPinDescriptor
, sizeof(KSPIN_DESCRIPTOR
));
1253 RtlMoveMemory((PVOID
)(PinDescriptors
+ This
->PinDescriptorCount
), &InPinDescriptor
->PinDescriptor
, sizeof(KSPIN_DESCRIPTOR
));
1255 /* replace old descriptor by using a gcc-compliant hack */
1256 RtlMoveMemory((PVOID
)&This
->Filter
.Descriptor
->PinDescriptors
, PinDescriptorsEx
, sizeof(KSPIN_DESCRIPTOR_EX
*));
1257 RtlMoveMemory((PVOID
)&This
->Filter
.Descriptor
->PinDescriptorsCount
, &Count
, sizeof(ULONG
));
1259 This
->PinDescriptors
= PinDescriptors
;
1260 This
->PinInstanceCount
= PinInstanceCount
;
1262 /* store new pin id */
1263 *PinID
= This
->PinDescriptorCount
;
1265 /* increment pin descriptor count */
1266 This
->PinDescriptorCount
++;
1268 return STATUS_SUCCESS
;
1279 IN PKSFILTER Filter
)
1291 KsFilterGetChildPinCount(
1292 IN PKSFILTER Filter
,
1295 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1297 if (PinId
>= This
->PinDescriptorCount
)
1299 /* index is out of bounds */
1302 /* return pin instance count */
1303 return This
->PinInstanceCount
[PinId
];
1312 KsFilterGetFirstChildPin(
1313 IN PKSFILTER Filter
,
1326 KsFilterRegisterPowerCallbacks(
1327 IN PKSFILTER Filter
,
1328 IN PFNKSFILTERPOWER Sleep OPTIONAL
,
1329 IN PFNKSFILTERPOWER Wake OPTIONAL
)
1331 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1333 This
->Sleep
= Sleep
;
1346 PIO_STACK_LOCATION IoStack
;
1347 PKSIOBJECT_HEADER ObjectHeader
;
1349 /* get current irp stack location */
1350 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1353 ASSERT(IoStack
->FileObject
);
1355 /* get object header */
1356 ObjectHeader
= (PKSIOBJECT_HEADER
)IoStack
->FileObject
->FsContext
;
1358 if (ObjectHeader
->Type
== KsObjectTypeFilter
)
1360 /* irp is targeted at the filter */
1361 return (PKSFILTER
)ObjectHeader
->ObjectType
;
1363 else if (ObjectHeader
->Type
== KsObjectTypePin
)
1365 /* irp is for a pin */
1366 return KsPinGetParentFilter((PKSPIN
)ObjectHeader
->ObjectType
);
1370 /* irp is unappropiate to retrieve a filter */