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_EX
* PinDescriptorsEx
;
25 KSPIN_DESCRIPTOR
* PinDescriptors
;
26 ULONG PinDescriptorCount
;
27 PKSFILTERFACTORY Factory
;
28 PFILE_OBJECT FileObject
;
30 KMUTEX ProcessingMutex
;
33 PFNKSFILTERPOWER Sleep
;
34 PFNKSFILTERPOWER Wake
;
36 ULONG
*PinInstanceCount
;
38 PKSPROCESSPIN_INDEXENTRY ProcessPinIndex
;
42 const GUID IID_IKsControl
= {0x28F54685L
, 0x06FD, 0x11D2, {0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
43 const GUID IID_IKsFilter
= {0x3ef6ee44L
, 0x0D41, 0x11d2, {0xbe, 0xDA, 0x00, 0xc0, 0x4f, 0x8e, 0xF4, 0x57}};
44 const GUID KSPROPSETID_Topology
= {0x720D4AC0L
, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
45 const GUID KSPROPSETID_Pin
= {0x8C134960L
, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
48 IKsFilter_RemoveFilterFromFilterFactory(
50 PKSFILTERFACTORY FilterFactory
);
53 DEFINE_KSPROPERTY_TOPOLOGYSET(IKsFilterTopologySet
, KspTopologyPropertyHandler
);
54 DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(IKsFilterPinSet
, KspPinPropertyHandler
, KspPinPropertyHandler
, KspPinPropertyHandler
);
56 KSPROPERTY_SET FilterPropertySet
[] =
59 &KSPROPSETID_Topology
,
60 sizeof(IKsFilterTopologySet
) / sizeof(KSPROPERTY_ITEM
),
61 (const KSPROPERTY_ITEM
*)&IKsFilterTopologySet
,
67 sizeof(IKsFilterPinSet
) / sizeof(KSPROPERTY_ITEM
),
68 (const KSPROPERTY_ITEM
*)&IKsFilterPinSet
,
76 IKsControl_fnQueryInterface(
81 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsControl
);
83 if (IsEqualGUIDAligned(refiid
, &IID_IUnknown
))
85 *Output
= &This
->lpVtbl
;
86 _InterlockedIncrement(&This
->ref
);
87 return STATUS_SUCCESS
;
89 return STATUS_UNSUCCESSFUL
;
97 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsControl
);
99 return InterlockedIncrement(&This
->ref
);
104 IKsControl_fnRelease(
107 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsControl
);
109 InterlockedDecrement(&This
->ref
);
111 /* Return new reference count */
117 IKsControl_fnKsProperty(
119 IN PKSPROPERTY Property
,
120 IN ULONG PropertyLength
,
121 IN OUT PVOID PropertyData
,
123 OUT ULONG
* BytesReturned
)
125 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsControl
);
127 return KsSynchronousIoControlDevice(This
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, Property
, PropertyLength
, PropertyData
, DataLength
, BytesReturned
);
133 IKsControl_fnKsMethod(
136 IN ULONG MethodLength
,
137 IN OUT PVOID MethodData
,
139 OUT ULONG
* BytesReturned
)
141 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsControl
);
143 return KsSynchronousIoControlDevice(This
->FileObject
, KernelMode
, IOCTL_KS_METHOD
, Method
, MethodLength
, MethodData
, DataLength
, BytesReturned
);
149 IKsControl_fnKsEvent(
151 IN PKSEVENT Event OPTIONAL
,
152 IN ULONG EventLength
,
153 IN OUT PVOID EventData
,
155 OUT ULONG
* BytesReturned
)
157 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtblKsControl
);
161 return KsSynchronousIoControlDevice(This
->FileObject
, KernelMode
, IOCTL_KS_ENABLE_EVENT
, Event
, EventLength
, EventData
, DataLength
, BytesReturned
);
165 return KsSynchronousIoControlDevice(This
->FileObject
, KernelMode
, IOCTL_KS_DISABLE_EVENT
, EventData
, DataLength
, NULL
, 0, BytesReturned
);
170 static IKsControlVtbl vt_IKsControl
=
172 IKsControl_fnQueryInterface
,
174 IKsControl_fnRelease
,
175 IKsControl_fnKsProperty
,
176 IKsControl_fnKsMethod
,
183 IKsFilter_fnQueryInterface(
188 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtbl
);
190 if (IsEqualGUIDAligned(refiid
, &IID_IUnknown
) ||
191 IsEqualGUIDAligned(refiid
, &IID_IKsFilter
))
193 *Output
= &This
->lpVtbl
;
194 _InterlockedIncrement(&This
->ref
);
195 return STATUS_SUCCESS
;
197 else if (IsEqualGUIDAligned(refiid
, &IID_IKsControl
))
199 *Output
= &This
->lpVtblKsControl
;
200 _InterlockedIncrement(&This
->ref
);
201 return STATUS_SUCCESS
;
204 return STATUS_UNSUCCESSFUL
;
212 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtbl
);
214 return InterlockedIncrement(&This
->ref
);
222 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtbl
);
224 InterlockedDecrement(&This
->ref
);
231 /* Return new reference count */
238 IKsFilter_fnGetStruct(
241 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtbl
);
243 return &This
->Filter
;
248 IKsFilter_fnDoAllNecessaryPinsExist(
257 IKsFilter_fnCreateNode(
261 IN PLIST_ENTRY ListEntry
)
264 return STATUS_NOT_IMPLEMENTED
;
269 IKsFilter_fnBindProcessPinsToPipeSection(
271 IN
struct KSPROCESSPIPESECTION
*Section
,
275 OUT PKSGATE
*OutGate
)
278 return STATUS_NOT_IMPLEMENTED
;
283 IKsFilter_fnUnbindProcessPinsFromPipeSection(
285 IN
struct KSPROCESSPIPESECTION
*Section
)
288 return STATUS_NOT_IMPLEMENTED
;
293 IKsFilter_fnAddProcessPin(
295 IN PKSPROCESSPIN ProcessPin
)
298 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtbl
);
300 /* first acquire processing mutex */
301 KeWaitForSingleObject(&This
->ProcessingMutex
, Executive
, KernelMode
, FALSE
, NULL
);
304 ASSERT(This
->PinDescriptorCount
> ProcessPin
->Pin
->Id
);
306 /* allocate new process pin array */
307 Status
= _KsEdit(This
->Filter
.Bag
, (PVOID
*)&This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Pins
,
308 (This
->PinDescriptorCount
+ 1) * sizeof(PKSPROCESSPIN
),
309 This
->PinDescriptorCount
* sizeof(PKSPROCESSPIN
),
312 if (NT_SUCCESS(Status
))
314 /* store process pin */
315 This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Pins
[This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Count
] = ProcessPin
;
316 This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Count
++;
319 /* release process mutex */
320 KeReleaseMutex(&This
->ProcessingMutex
, FALSE
);
327 IKsFilter_fnRemoveProcessPin(
329 IN PKSPROCESSPIN ProcessPin
)
333 PKSPROCESSPIN
* Pins
;
335 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtbl
);
337 /* first acquire processing mutex */
338 KeWaitForSingleObject(&This
->ProcessingMutex
, Executive
, KernelMode
, FALSE
, NULL
);
341 ASSERT(ProcessPin
->Pin
);
342 ASSERT(ProcessPin
->Pin
->Id
);
344 Count
= This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Count
;
345 Pins
= This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Pins
;
347 /* search for current process pin */
348 for(Index
= 0; Index
< Count
; Index
++)
350 if (Pins
[Index
] == ProcessPin
)
352 RtlMoveMemory(&Pins
[Index
], &Pins
[Index
+ 1], (Count
- (Index
+ 1)) * sizeof(PKSPROCESSPIN
));
358 /* decrement pin count */
359 This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Count
--;
361 if (!This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Count
)
363 /* clear entry object bag will delete it */
364 This
->ProcessPinIndex
[ProcessPin
->Pin
->Id
].Pins
= NULL
;
367 /* release process mutex */
368 KeReleaseMutex(&This
->ProcessingMutex
, FALSE
);
371 return STATUS_SUCCESS
;
376 IKsFilter_fnReprepareProcessPipeSection(
378 IN
struct KSPROCESSPIPESECTION
*PipeSection
,
387 IKsFilter_fnDeliverResetState(
389 IN
struct KSPROCESSPIPESECTION
*PipeSection
,
390 IN KSRESET ResetState
)
397 IKsFilter_fnIsFrameHolding(
406 IKsFilter_fnRegisterForCopyCallbacks(
414 PKSPROCESSPIN_INDEXENTRY
416 IKsFilter_fnGetProcessDispatch(
419 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(iface
, IKsFilterImpl
, lpVtbl
);
421 return This
->ProcessPinIndex
;
424 static IKsFilterVtbl vt_IKsFilter
=
426 IKsFilter_fnQueryInterface
,
429 IKsFilter_fnGetStruct
,
430 IKsFilter_fnDoAllNecessaryPinsExist
,
431 IKsFilter_fnCreateNode
,
432 IKsFilter_fnBindProcessPinsToPipeSection
,
433 IKsFilter_fnUnbindProcessPinsFromPipeSection
,
434 IKsFilter_fnAddProcessPin
,
435 IKsFilter_fnRemoveProcessPin
,
436 IKsFilter_fnReprepareProcessPipeSection
,
437 IKsFilter_fnDeliverResetState
,
438 IKsFilter_fnIsFrameHolding
,
439 IKsFilter_fnRegisterForCopyCallbacks
,
440 IKsFilter_fnGetProcessDispatch
444 IKsFilter_GetFilterFromIrp(
446 OUT IKsFilter
**Filter
)
448 PIO_STACK_LOCATION IoStack
;
449 PKSIOBJECT_HEADER ObjectHeader
;
452 /* get current irp stack */
453 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
456 ASSERT(IoStack
->FileObject
!= NULL
);
458 ObjectHeader
= (PKSIOBJECT_HEADER
)IoStack
->FileObject
->FsContext2
;
460 /* sanity is important */
461 ASSERT(ObjectHeader
!= NULL
);
462 ASSERT(ObjectHeader
->Type
== KsObjectTypeFilter
);
463 ASSERT(ObjectHeader
->Unknown
!= NULL
);
465 /* get our private interface */
466 Status
= ObjectHeader
->Unknown
->lpVtbl
->QueryInterface(ObjectHeader
->Unknown
, &IID_IKsFilter
, (PVOID
*)Filter
);
468 if (!NT_SUCCESS(Status
))
470 /* something is wrong here */
471 DPRINT1("KS: Misbehaving filter %p\n", ObjectHeader
->Unknown
);
472 Irp
->IoStatus
.Status
= Status
;
474 /* complete and forget irp */
475 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
484 IKsFilter_DispatchClose(
485 IN PDEVICE_OBJECT DeviceObject
,
489 IKsFilterImpl
* This
;
492 /* obtain filter from object header */
493 Status
= IKsFilter_GetFilterFromIrp(Irp
, &Filter
);
494 if (!NT_SUCCESS(Status
))
497 /* get our real implementation */
498 This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, lpVtbl
);
500 /* does the driver support notifications */
501 if (This
->Factory
->FilterDescriptor
&& This
->Factory
->FilterDescriptor
->Dispatch
&& This
->Factory
->FilterDescriptor
->Dispatch
->Close
)
503 /* call driver's filter close function */
504 Status
= This
->Factory
->FilterDescriptor
->Dispatch
->Close(&This
->Filter
, Irp
);
507 if (NT_SUCCESS(Status
) && Status
!= STATUS_PENDING
)
509 /* save the result */
510 Irp
->IoStatus
.Status
= Status
;
512 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
514 /* remove our instance from the filter factory */
515 IKsFilter_RemoveFilterFromFilterFactory(This
, This
->Factory
);
517 /* free object header */
518 KsFreeObjectHeader(This
->ObjectHeader
);
522 /* complete and forget */
523 Irp
->IoStatus
.Status
= Status
;
525 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
533 KspHandlePropertyInstances(
534 IN PIO_STATUS_BLOCK IoStatus
,
535 IN PKSIDENTIFIER Request
,
537 IN IKsFilterImpl
* This
,
540 KSPIN_CINSTANCES
* Instances
;
541 KSP_PIN
* Pin
= (KSP_PIN
*)Request
;
543 if (!This
->Factory
->FilterDescriptor
|| !This
->PinDescriptorCount
)
545 /* no filter / pin descriptor */
546 IoStatus
->Status
= STATUS_NOT_IMPLEMENTED
;
547 return STATUS_NOT_IMPLEMENTED
;
550 /* ignore custom structs for now */
551 ASSERT(This
->Factory
->FilterDescriptor
->PinDescriptorSize
== sizeof(KSPIN_DESCRIPTOR_EX
));
552 ASSERT(This
->PinDescriptorCount
> Pin
->PinId
);
554 Instances
= (KSPIN_CINSTANCES
*)Data
;
555 /* max instance count */
556 Instances
->PossibleCount
= This
->PinDescriptorsEx
[Pin
->PinId
].InstancesPossible
;
557 /* current instance count */
558 Instances
->CurrentCount
= This
->PinInstanceCount
[Pin
->PinId
];
560 IoStatus
->Information
= sizeof(KSPIN_CINSTANCES
);
561 IoStatus
->Status
= STATUS_SUCCESS
;
562 return STATUS_SUCCESS
;
566 KspHandleNecessaryPropertyInstances(
567 IN PIO_STATUS_BLOCK IoStatus
,
568 IN PKSIDENTIFIER Request
,
570 IN IKsFilterImpl
* This
)
573 KSP_PIN
* Pin
= (KSP_PIN
*)Request
;
575 if (!This
->Factory
->FilterDescriptor
|| !This
->PinDescriptorCount
)
577 /* no filter / pin descriptor */
578 IoStatus
->Status
= STATUS_NOT_IMPLEMENTED
;
579 return STATUS_NOT_IMPLEMENTED
;
582 /* ignore custom structs for now */
583 ASSERT(This
->Factory
->FilterDescriptor
->PinDescriptorSize
== sizeof(KSPIN_DESCRIPTOR_EX
));
584 ASSERT(This
->PinDescriptorCount
> Pin
->PinId
);
586 Result
= (PULONG
)Data
;
587 *Result
= This
->PinDescriptorsEx
[Pin
->PinId
].InstancesNecessary
;
589 IoStatus
->Information
= sizeof(ULONG
);
590 IoStatus
->Status
= STATUS_SUCCESS
;
591 return STATUS_SUCCESS
;
595 KspHandleDataIntersection(
597 IN PIO_STATUS_BLOCK IoStatus
,
598 IN PKSIDENTIFIER Request
,
601 IN IKsFilterImpl
* This
)
603 PKSMULTIPLE_ITEM MultipleItem
;
604 PKSDATARANGE DataRange
;
605 NTSTATUS Status
= STATUS_NO_MATCH
;
607 KSP_PIN
* Pin
= (KSP_PIN
*)Request
;
609 /* Access parameters */
610 MultipleItem
= (PKSMULTIPLE_ITEM
)(Pin
+ 1);
611 DataRange
= (PKSDATARANGE
)(MultipleItem
+ 1);
613 /* FIXME make sure its 64 bit aligned */
614 ASSERT(((ULONG_PTR
)DataRange
& 0x7) == 0);
616 if (!This
->Factory
->FilterDescriptor
|| !This
->PinDescriptorCount
)
618 /* no filter / pin descriptor */
619 IoStatus
->Status
= STATUS_NOT_IMPLEMENTED
;
620 return STATUS_NOT_IMPLEMENTED
;
623 /* ignore custom structs for now */
624 ASSERT(This
->Factory
->FilterDescriptor
->PinDescriptorSize
== sizeof(KSPIN_DESCRIPTOR_EX
));
625 ASSERT(This
->PinDescriptorCount
> Pin
->PinId
);
627 if (This
->PinDescriptorsEx
[Pin
->PinId
].IntersectHandler
== NULL
||
628 This
->PinDescriptors
[Pin
->PinId
].DataRanges
== NULL
||
629 This
->PinDescriptors
[Pin
->PinId
].DataRangesCount
== 0)
631 /* no driver supported intersect handler / no provided data ranges */
632 IoStatus
->Status
= STATUS_NOT_IMPLEMENTED
;
633 return STATUS_NOT_IMPLEMENTED
;
636 for(Index
= 0; Index
< MultipleItem
->Count
; Index
++)
638 UNICODE_STRING MajorFormat
, SubFormat
, Specifier
;
639 /* convert the guid to string */
640 RtlStringFromGUID(&DataRange
->MajorFormat
, &MajorFormat
);
641 RtlStringFromGUID(&DataRange
->SubFormat
, &SubFormat
);
642 RtlStringFromGUID(&DataRange
->Specifier
, &Specifier
);
644 DPRINT("Index %lu MajorFormat %S SubFormat %S Specifier %S FormatSize %lu SampleSize %lu Align %lu Flags %lx Reserved %lx DataLength %lu\n", Index
, MajorFormat
.Buffer
, SubFormat
.Buffer
, Specifier
.Buffer
,
645 DataRange
->FormatSize
, DataRange
->SampleSize
, DataRange
->Alignment
, DataRange
->Flags
, DataRange
->Reserved
, DataLength
);
647 /* FIXME implement KsPinDataIntersectionEx */
648 /* Call miniport's properitary handler */
649 Status
= This
->PinDescriptorsEx
[Pin
->PinId
].IntersectHandler(&This
->Filter
,
653 This
->PinDescriptorsEx
[Pin
->PinId
].PinDescriptor
.DataRanges
[0], /* HACK */
658 if (Status
== STATUS_SUCCESS
|| Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
661 IoStatus
->Information
= Length
;
662 if (Status
!= STATUS_SUCCESS
)
663 Status
= STATUS_MORE_ENTRIES
;
667 DataRange
= UlongToPtr(PtrToUlong(DataRange
) + DataRange
->FormatSize
);
668 /* FIXME make sure its 64 bit aligned */
669 ASSERT(((ULONG_PTR
)DataRange
& 0x7) == 0);
672 IoStatus
->Status
= Status
;
678 KspTopologyPropertyHandler(
680 IN PKSIDENTIFIER Request
,
683 IKsFilterImpl
* This
;
685 /* get filter implementation */
686 This
= (IKsFilterImpl
*)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
691 return KsTopologyPropertyHandler(Irp
, Request
, Data
, &This
->Topology
);
698 KspPinPropertyHandler(
700 IN PKSIDENTIFIER Request
,
703 PIO_STACK_LOCATION IoStack
;
704 IKsFilterImpl
* This
;
705 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
707 /* get filter implementation */
708 This
= (IKsFilterImpl
*)KSPROPERTY_ITEM_IRP_STORAGE(Irp
);
713 /* get current stack location */
714 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
718 case KSPROPERTY_PIN_CTYPES
:
719 case KSPROPERTY_PIN_DATAFLOW
:
720 case KSPROPERTY_PIN_DATARANGES
:
721 case KSPROPERTY_PIN_INTERFACES
:
722 case KSPROPERTY_PIN_MEDIUMS
:
723 case KSPROPERTY_PIN_COMMUNICATION
:
724 case KSPROPERTY_PIN_CATEGORY
:
725 case KSPROPERTY_PIN_NAME
:
726 case KSPROPERTY_PIN_CONSTRAINEDDATARANGES
:
727 Status
= KsPinPropertyHandler(Irp
, Request
, Data
, This
->PinDescriptorCount
, This
->PinDescriptors
);
729 case KSPROPERTY_PIN_GLOBALCINSTANCES
:
730 Status
= KspHandlePropertyInstances(&Irp
->IoStatus
, Request
, Data
, This
, TRUE
);
732 case KSPROPERTY_PIN_CINSTANCES
:
733 Status
= KspHandlePropertyInstances(&Irp
->IoStatus
, Request
, Data
, This
, FALSE
);
735 case KSPROPERTY_PIN_NECESSARYINSTANCES
:
736 Status
= KspHandleNecessaryPropertyInstances(&Irp
->IoStatus
, Request
, Data
, This
);
739 case KSPROPERTY_PIN_DATAINTERSECTION
:
740 Status
= KspHandleDataIntersection(Irp
, &Irp
->IoStatus
, Request
, Data
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
, This
);
744 Status
= STATUS_NOT_FOUND
;
746 //DPRINT("KspPinPropertyHandler Pins %lu Request->Id %lu Status %lx\n", This->PinDescriptorCount, Request->Id, Status);
754 IKsFilter_DispatchDeviceIoControl(
755 IN PDEVICE_OBJECT DeviceObject
,
758 PIO_STACK_LOCATION IoStack
;
760 IKsFilterImpl
* This
;
762 PKSFILTER FilterInstance
;
763 UNICODE_STRING GuidString
;
764 PKSPROPERTY Property
;
767 /* obtain filter from object header */
768 Status
= IKsFilter_GetFilterFromIrp(Irp
, &Filter
);
769 if (!NT_SUCCESS(Status
))
772 /* get our real implementation */
773 This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, lpVtbl
);
775 /* current irp stack */
776 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
778 /* get property from input buffer */
779 Property
= (PKSPROPERTY
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
781 /* get filter instance */
782 FilterInstance
= Filter
->lpVtbl
->GetStruct(Filter
);
786 ASSERT(IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
>= sizeof(KSIDENTIFIER
));
787 ASSERT(FilterInstance
);
788 ASSERT(FilterInstance
->Descriptor
);
789 ASSERT(FilterInstance
->Descriptor
->AutomationTable
);
791 RtlStringFromGUID(&Property
->Set
, &GuidString
);
792 DPRINT("IKsFilter_DispatchDeviceIoControl property Set |%S| Id %u Flags %x\n", GuidString
.Buffer
, Property
->Id
, Property
->Flags
);
793 RtlFreeUnicodeString(&GuidString
);
795 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_METHOD
)
797 const KSMETHOD_SET
*MethodSet
= NULL
;
798 ULONG MethodItemSize
= 0;
800 /* check if the driver supports method sets */
801 if (FilterInstance
->Descriptor
->AutomationTable
->MethodSetsCount
)
803 SetCount
= FilterInstance
->Descriptor
->AutomationTable
->MethodSetsCount
;
804 MethodSet
= FilterInstance
->Descriptor
->AutomationTable
->MethodSets
;
805 MethodItemSize
= FilterInstance
->Descriptor
->AutomationTable
->MethodItemSize
;
808 /* call method set handler */
809 Status
= KspMethodHandlerWithAllocator(Irp
, SetCount
, MethodSet
, NULL
, MethodItemSize
);
811 else if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_PROPERTY
)
813 const KSPROPERTY_SET
*PropertySet
= NULL
;
814 ULONG PropertyItemSize
= 0;
816 /* check if the driver supports method sets */
817 if (FilterInstance
->Descriptor
->AutomationTable
->PropertySetsCount
)
819 SetCount
= FilterInstance
->Descriptor
->AutomationTable
->PropertySetsCount
;
820 PropertySet
= FilterInstance
->Descriptor
->AutomationTable
->PropertySets
;
821 PropertyItemSize
= FilterInstance
->Descriptor
->AutomationTable
->PropertyItemSize
;
824 /* needed for our property handlers */
825 KSPROPERTY_ITEM_IRP_STORAGE(Irp
) = (KSPROPERTY_ITEM
*)This
;
827 /* call property handler */
828 Status
= KspPropertyHandler(Irp
, SetCount
, PropertySet
, NULL
, PropertyItemSize
);
833 ASSERT(IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_ENABLE_EVENT
||
834 IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_DISABLE_EVENT
);
836 if (IoStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_KS_ENABLE_EVENT
)
838 /* call enable event handlers */
839 Status
= KspEnableEvent(Irp
,
840 FilterInstance
->Descriptor
->AutomationTable
->EventSetsCount
,
841 (PKSEVENT_SET
)FilterInstance
->Descriptor
->AutomationTable
->EventSets
,
842 &This
->Header
.EventList
,
844 (PVOID
)&This
->Header
.EventListLock
,
846 FilterInstance
->Descriptor
->AutomationTable
->EventItemSize
);
850 /* disable event handler */
851 Status
= KsDisableEvent(Irp
, &This
->Header
.EventList
, KSEVENTS_SPINLOCK
, &This
->Header
.EventListLock
);
855 RtlStringFromGUID(&Property
->Set
, &GuidString
);
856 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
);
857 RtlFreeUnicodeString(&GuidString
);
860 Filter
->lpVtbl
->Release(Filter
);
862 if (Status
!= STATUS_PENDING
)
864 Irp
->IoStatus
.Status
= Status
;
865 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
872 static KSDISPATCH_TABLE DispatchTable
=
874 IKsFilter_DispatchDeviceIoControl
,
875 KsDispatchInvalidDeviceRequest
,
876 KsDispatchInvalidDeviceRequest
,
877 KsDispatchInvalidDeviceRequest
,
878 IKsFilter_DispatchClose
,
879 KsDispatchQuerySecurity
,
880 KsDispatchSetSecurity
,
881 KsDispatchFastIoDeviceControlFailure
,
882 KsDispatchFastReadFailure
,
883 KsDispatchFastReadFailure
,
888 IKsFilter_CreateDescriptors(
889 IKsFilterImpl
* This
,
890 KSFILTER_DESCRIPTOR
* FilterDescriptor
)
895 /* initialize pin descriptors */
896 This
->FirstPin
= NULL
;
897 This
->PinInstanceCount
= NULL
;
898 This
->PinDescriptors
= NULL
;
899 This
->PinDescriptorsEx
= NULL
;
900 This
->ProcessPinIndex
= NULL
;
901 This
->PinDescriptorCount
= 0;
903 /* initialize topology descriptor */
904 This
->Topology
.CategoriesCount
= FilterDescriptor
->CategoriesCount
;
905 This
->Topology
.Categories
= FilterDescriptor
->Categories
;
906 This
->Topology
.TopologyNodesCount
= FilterDescriptor
->NodeDescriptorsCount
;
907 This
->Topology
.TopologyConnectionsCount
= FilterDescriptor
->ConnectionsCount
;
908 This
->Topology
.TopologyConnections
= FilterDescriptor
->Connections
;
910 /* are there any templates */
911 if (FilterDescriptor
->PinDescriptorsCount
)
914 ASSERT(FilterDescriptor
->PinDescriptors
);
916 /* FIXME handle variable sized pin descriptors */
917 ASSERT(FilterDescriptor
->PinDescriptorSize
== sizeof(KSPIN_DESCRIPTOR_EX
));
919 /* store pin descriptors ex */
920 Status
= _KsEdit(This
->Filter
.Bag
, (PVOID
*)&This
->PinDescriptorsEx
, sizeof(KSPIN_DESCRIPTOR_EX
) * FilterDescriptor
->PinDescriptorsCount
,
921 sizeof(KSPIN_DESCRIPTOR_EX
) * FilterDescriptor
->PinDescriptorsCount
, 0);
923 if (!NT_SUCCESS(Status
))
925 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status
);
929 /* store pin descriptors */
930 Status
= _KsEdit(This
->Filter
.Bag
, (PVOID
*)&This
->PinDescriptors
, sizeof(KSPIN_DESCRIPTOR
) * FilterDescriptor
->PinDescriptorsCount
,
931 sizeof(KSPIN_DESCRIPTOR
) * FilterDescriptor
->PinDescriptorsCount
, 0);
933 if (!NT_SUCCESS(Status
))
935 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status
);
939 /* store pin instance count ex */
940 Status
= _KsEdit(This
->Filter
.Bag
, (PVOID
*)&This
->PinInstanceCount
, sizeof(ULONG
) * FilterDescriptor
->PinDescriptorsCount
,
941 sizeof(ULONG
) * FilterDescriptor
->PinDescriptorsCount
, 0);
943 if (!NT_SUCCESS(Status
))
945 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status
);
949 /* store instantiated pin arrays */
950 Status
= _KsEdit(This
->Filter
.Bag
, (PVOID
*)&This
->FirstPin
, sizeof(PKSPIN
) * FilterDescriptor
->PinDescriptorsCount
,
951 sizeof(PKSPIN
) * FilterDescriptor
->PinDescriptorsCount
, 0);
953 if (!NT_SUCCESS(Status
))
955 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status
);
959 /* add new pin factory */
960 RtlMoveMemory(This
->PinDescriptorsEx
, FilterDescriptor
->PinDescriptors
, sizeof(KSPIN_DESCRIPTOR_EX
) * FilterDescriptor
->PinDescriptorsCount
);
962 for(Index
= 0; Index
< FilterDescriptor
->PinDescriptorsCount
; Index
++)
964 RtlMoveMemory(&This
->PinDescriptors
[Index
], &FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
, sizeof(KSPIN_DESCRIPTOR
));
967 /* allocate process pin index */
968 Status
= _KsEdit(This
->Filter
.Bag
, (PVOID
*)&This
->ProcessPinIndex
, sizeof(KSPROCESSPIN_INDEXENTRY
) * FilterDescriptor
->PinDescriptorsCount
,
969 sizeof(KSPROCESSPIN_INDEXENTRY
) * FilterDescriptor
->PinDescriptorsCount
, 0);
971 if (!NT_SUCCESS(Status
))
973 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status
);
977 /* store new pin descriptor count */
978 This
->PinDescriptorCount
= FilterDescriptor
->PinDescriptorsCount
;
982 if (FilterDescriptor
->NodeDescriptorsCount
)
985 ASSERT(FilterDescriptor
->NodeDescriptors
);
987 /* FIXME handle variable sized node descriptors */
988 ASSERT(FilterDescriptor
->NodeDescriptorSize
== sizeof(KSNODE_DESCRIPTOR
));
990 This
->Topology
.TopologyNodes
= AllocateItem(NonPagedPool
, sizeof(GUID
) * FilterDescriptor
->NodeDescriptorsCount
);
991 /* allocate topology node types array */
992 if (!This
->Topology
.TopologyNodes
)
994 DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor
->NodeDescriptorsCount
);
995 return STATUS_INSUFFICIENT_RESOURCES
;
998 This
->Topology
.TopologyNodesNames
= AllocateItem(NonPagedPool
, sizeof(GUID
) * FilterDescriptor
->NodeDescriptorsCount
);
999 /* allocate topology names array */
1000 if (!This
->Topology
.TopologyNodesNames
)
1002 FreeItem((PVOID
)This
->Topology
.TopologyNodes
);
1003 DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor
->NodeDescriptorsCount
);
1004 return STATUS_INSUFFICIENT_RESOURCES
;
1007 DPRINT("NodeDescriptorCount %lu\n", FilterDescriptor
->NodeDescriptorsCount
);
1008 for(Index
= 0; Index
< FilterDescriptor
->NodeDescriptorsCount
; Index
++)
1010 DPRINT("Index %lu Type %p Name %p\n", Index
, FilterDescriptor
->NodeDescriptors
[Index
].Type
, FilterDescriptor
->NodeDescriptors
[Index
].Name
);
1012 /* copy topology type */
1013 if (FilterDescriptor
->NodeDescriptors
[Index
].Type
)
1014 RtlMoveMemory((PVOID
)&This
->Topology
.TopologyNodes
[Index
], FilterDescriptor
->NodeDescriptors
[Index
].Type
, sizeof(GUID
));
1016 /* copy topology name */
1017 if (FilterDescriptor
->NodeDescriptors
[Index
].Name
)
1018 RtlMoveMemory((PVOID
)&This
->Topology
.TopologyNodesNames
[Index
], FilterDescriptor
->NodeDescriptors
[Index
].Name
, sizeof(GUID
));
1022 return STATUS_SUCCESS
;
1026 IKsFilter_CopyFilterDescriptor(
1027 IKsFilterImpl
* This
,
1028 const KSFILTER_DESCRIPTOR
* FilterDescriptor
)
1031 KSAUTOMATION_TABLE AutomationTable
;
1033 This
->Filter
.Descriptor
= AllocateItem(NonPagedPool
, sizeof(KSFILTER_DESCRIPTOR
));
1034 if (!This
->Filter
.Descriptor
)
1035 return STATUS_INSUFFICIENT_RESOURCES
;
1037 Status
= KsAddItemToObjectBag(This
->Filter
.Bag
, (PVOID
)This
->Filter
.Descriptor
, NULL
);
1038 if (!NT_SUCCESS(Status
))
1040 FreeItem((PVOID
)This
->Filter
.Descriptor
);
1041 This
->Filter
.Descriptor
= NULL
;
1042 return STATUS_INSUFFICIENT_RESOURCES
;
1045 /* copy filter descriptor fields */
1046 RtlMoveMemory((PVOID
)This
->Filter
.Descriptor
, FilterDescriptor
, sizeof(KSFILTER_DESCRIPTOR
));
1048 /* zero automation table */
1049 RtlZeroMemory(&AutomationTable
, sizeof(KSAUTOMATION_TABLE
));
1051 /* setup filter property sets */
1052 AutomationTable
.PropertyItemSize
= sizeof(KSPROPERTY_ITEM
);
1053 AutomationTable
.PropertySetsCount
= 2;
1054 AutomationTable
.PropertySets
= FilterPropertySet
;
1056 /* merge filter automation table */
1057 Status
= KsMergeAutomationTables((PKSAUTOMATION_TABLE
*)&This
->Filter
.Descriptor
->AutomationTable
, (PKSAUTOMATION_TABLE
)FilterDescriptor
->AutomationTable
, &AutomationTable
, This
->Filter
.Bag
);
1068 PKSPIN NextPin
, CurPin
;
1069 PKSBASIC_HEADER BasicHeader
;
1070 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1073 ASSERT(Pin
->Id
< This
->PinDescriptorCount
);
1075 if (This
->FirstPin
[Pin
->Id
] == NULL
)
1077 /* welcome first pin */
1078 This
->FirstPin
[Pin
->Id
] = Pin
;
1079 This
->PinInstanceCount
[Pin
->Id
]++;
1084 CurPin
= This
->FirstPin
[Pin
->Id
];
1088 /* get next instantiated pin */
1089 NextPin
= KsPinGetNextSiblingPin(CurPin
);
1095 }while(NextPin
!= NULL
);
1097 /* get basic header */
1098 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)CurPin
- sizeof(KSBASIC_HEADER
));
1101 BasicHeader
->Next
.Pin
= Pin
;
1105 IKsFilter_RemovePin(
1109 PKSPIN NextPin
, CurPin
, LastPin
;
1110 PKSBASIC_HEADER BasicHeader
;
1111 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1114 ASSERT(Pin
->Id
< This
->PinDescriptorCount
);
1117 CurPin
= This
->FirstPin
[Pin
->Id
];
1122 /* get next instantiated pin */
1123 NextPin
= KsPinGetNextSiblingPin(CurPin
);
1129 /* get basic header of last pin */
1130 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)LastPin
- sizeof(KSBASIC_HEADER
));
1132 BasicHeader
->Next
.Pin
= NextPin
;
1136 /* erase last pin */
1137 This
->FirstPin
[Pin
->Id
] = NextPin
;
1139 /* decrement pin instance count */
1140 This
->PinInstanceCount
[Pin
->Id
]--;
1150 }while(NextPin
!= NULL
);
1159 IKsFilter_DispatchCreatePin(
1160 IN PDEVICE_OBJECT DeviceObject
,
1163 IKsFilterImpl
* This
;
1164 PKSOBJECT_CREATE_ITEM CreateItem
;
1165 PKSPIN_CONNECT Connect
;
1168 DPRINT("IKsFilter_DispatchCreatePin\n");
1170 /* get the create item */
1171 CreateItem
= KSCREATE_ITEM_IRP_STORAGE(Irp
);
1173 /* get the filter object */
1174 This
= (IKsFilterImpl
*)CreateItem
->Context
;
1177 ASSERT(This
->Header
.Type
== KsObjectTypeFilter
);
1179 /* acquire control mutex */
1180 KeWaitForSingleObject(This
->Header
.ControlMutex
, Executive
, KernelMode
, FALSE
, NULL
);
1182 /* now validate the connect request */
1183 Status
= KsValidateConnectRequest(Irp
, This
->PinDescriptorCount
, This
->PinDescriptors
, &Connect
);
1185 DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest %lx\n", Status
);
1187 if (NT_SUCCESS(Status
))
1190 ASSERT(Connect
->PinId
< This
->PinDescriptorCount
);
1192 DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest PinId %lu CurrentInstanceCount %lu MaxPossible %lu\n", Connect
->PinId
,
1193 This
->PinInstanceCount
[Connect
->PinId
],
1194 This
->PinDescriptorsEx
[Connect
->PinId
].InstancesPossible
);
1196 if (This
->PinInstanceCount
[Connect
->PinId
] < This
->PinDescriptorsEx
[Connect
->PinId
].InstancesPossible
)
1198 /* create the pin */
1199 Status
= KspCreatePin(DeviceObject
, Irp
, This
->Header
.KsDevice
, This
->FilterFactory
, (IKsFilter
*)&This
->lpVtbl
, Connect
, &This
->PinDescriptorsEx
[Connect
->PinId
]);
1201 DPRINT("IKsFilter_DispatchCreatePin KspCreatePin %lx\n", Status
);
1205 /* maximum instance count reached, bye-bye */
1206 Status
= STATUS_UNSUCCESSFUL
;
1207 DPRINT("IKsFilter_DispatchCreatePin MaxInstance %lu CurInstance %lu %lx\n", This
->PinDescriptorsEx
[Connect
->PinId
].InstancesPossible
, This
->PinInstanceCount
[Connect
->PinId
]);
1211 /* release control mutex */
1212 KeReleaseMutex(This
->Header
.ControlMutex
, FALSE
);
1214 if (Status
!= STATUS_PENDING
)
1216 /* complete request */
1217 Irp
->IoStatus
.Status
= Status
;
1218 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1222 DPRINT("IKsFilter_DispatchCreatePin Result %lx\n", Status
);
1228 IKsFilter_DispatchCreateNode(
1229 IN PDEVICE_OBJECT DeviceObject
,
1233 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
1234 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1235 return STATUS_UNSUCCESSFUL
;
1240 IKsFilter_AttachFilterToFilterFactory(
1241 IKsFilterImpl
* This
,
1242 PKSFILTERFACTORY FilterFactory
)
1244 PKSBASIC_HEADER BasicHeader
;
1248 /* get filter factory basic header */
1249 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)FilterFactory
- sizeof(KSBASIC_HEADER
));
1252 ASSERT(BasicHeader
->Type
== KsObjectTypeFilterFactory
);
1254 if (BasicHeader
->FirstChild
.FilterFactory
== NULL
)
1256 /* welcome first instantiated filter */
1257 BasicHeader
->FirstChild
.Filter
= &This
->Filter
;
1261 /* set to first entry */
1262 Filter
= BasicHeader
->FirstChild
.Filter
;
1266 /* get basic header */
1267 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)Filter
- sizeof(KSBASIC_HEADER
));
1269 ASSERT(BasicHeader
->Type
== KsObjectTypeFilter
);
1271 if (BasicHeader
->Next
.Filter
)
1273 /* iterate to next filter factory */
1274 Filter
= BasicHeader
->Next
.Filter
;
1278 /* found last entry */
1283 /* attach filter factory */
1284 BasicHeader
->Next
.Filter
= &This
->Filter
;
1288 IKsFilter_RemoveFilterFromFilterFactory(
1289 IKsFilterImpl
* This
,
1290 PKSFILTERFACTORY FilterFactory
)
1292 PKSBASIC_HEADER BasicHeader
;
1293 PKSFILTER Filter
, LastFilter
;
1295 /* get filter factory basic header */
1296 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)FilterFactory
- sizeof(KSBASIC_HEADER
));
1299 ASSERT(BasicHeader
->Type
== KsObjectTypeFilterFactory
);
1300 ASSERT(BasicHeader
->FirstChild
.Filter
!= NULL
);
1303 /* set to first entry */
1304 Filter
= BasicHeader
->FirstChild
.Filter
;
1309 if (Filter
== &This
->Filter
)
1313 /* get basic header */
1314 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)LastFilter
- sizeof(KSBASIC_HEADER
));
1315 /* remove filter instance */
1316 BasicHeader
->Next
.Filter
= This
->Header
.Next
.Filter
;
1321 /* remove filter instance */
1322 BasicHeader
->FirstChild
.Filter
= This
->Header
.Next
.Filter
;
1327 /* get basic header */
1328 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)Filter
- sizeof(KSBASIC_HEADER
));
1330 ASSERT(BasicHeader
->Type
== KsObjectTypeFilter
);
1332 LastFilter
= Filter
;
1333 if (BasicHeader
->Next
.Filter
)
1335 /* iterate to next filter factory */
1336 Filter
= BasicHeader
->Next
.Filter
;
1340 /* filter is not in list */
1350 IN PDEVICE_OBJECT DeviceObject
,
1352 IN IKsFilterFactory
*iface
)
1354 IKsFilterImpl
* This
;
1355 IKsDevice
*KsDevice
;
1356 PKSFILTERFACTORY Factory
;
1357 PIO_STACK_LOCATION IoStack
;
1358 PDEVICE_EXTENSION DeviceExtension
;
1360 PKSOBJECT_CREATE_ITEM CreateItem
;
1362 /* get device extension */
1363 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1365 /* get the filter factory */
1366 Factory
= iface
->lpVtbl
->GetStruct(iface
);
1368 if (!Factory
|| !Factory
->FilterDescriptor
|| !Factory
->FilterDescriptor
->Dispatch
|| !Factory
->FilterDescriptor
->Dispatch
->Create
)
1370 /* Sorry it just will not work */
1371 return STATUS_UNSUCCESSFUL
;
1374 /* allocate filter instance */
1375 This
= AllocateItem(NonPagedPool
, sizeof(IKsFilterImpl
));
1378 DPRINT("KspCreateFilter OutOfMemory\n");
1379 return STATUS_INSUFFICIENT_RESOURCES
;
1382 /* initialize object bag */
1383 This
->Filter
.Bag
= AllocateItem(NonPagedPool
, sizeof(KSIOBJECT_BAG
));
1384 if (!This
->Filter
.Bag
)
1388 DPRINT("KspCreateFilter OutOfMemory\n");
1389 return STATUS_INSUFFICIENT_RESOURCES
;
1391 KsDevice
= (IKsDevice
*)&DeviceExtension
->DeviceHeader
->lpVtblIKsDevice
;
1392 KsDevice
->lpVtbl
->InitializeObjectBag(KsDevice
, (PKSIOBJECT_BAG
)This
->Filter
.Bag
, NULL
);
1394 /* copy filter descriptor */
1395 Status
= IKsFilter_CopyFilterDescriptor(This
, Factory
->FilterDescriptor
);
1396 if (!NT_SUCCESS(Status
))
1398 /* not enough memory */
1399 FreeItem(This
->Filter
.Bag
);
1401 DPRINT("KspCreateFilter IKsFilter_CopyFilterDescriptor failed %lx\n", Status
);
1402 return STATUS_INSUFFICIENT_RESOURCES
;
1405 /* get current irp stack */
1406 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1408 /* allocate create items */
1409 CreateItem
= AllocateItem(NonPagedPool
, sizeof(KSOBJECT_CREATE_ITEM
) * 2);
1413 FreeItem(This
->Filter
.Bag
);
1415 DPRINT("KspCreateFilter OutOfMemory\n");
1416 return STATUS_INSUFFICIENT_RESOURCES
;
1419 DPRINT("KspCreateFilter Flags %lx\n", Factory
->FilterDescriptor
->Flags
);
1421 /* initialize pin create item */
1422 CreateItem
[0].Create
= IKsFilter_DispatchCreatePin
;
1423 CreateItem
[0].Context
= (PVOID
)This
;
1424 CreateItem
[0].Flags
= KSCREATE_ITEM_FREEONSTOP
;
1425 RtlInitUnicodeString(&CreateItem
[0].ObjectClass
, KSSTRING_Pin
);
1426 /* initialize node create item */
1427 CreateItem
[1].Create
= IKsFilter_DispatchCreateNode
;
1428 CreateItem
[1].Context
= (PVOID
)This
;
1429 CreateItem
[1].Flags
= KSCREATE_ITEM_FREEONSTOP
;
1430 RtlInitUnicodeString(&CreateItem
[1].ObjectClass
, KSSTRING_TopologyNode
);
1433 /* initialize filter instance */
1435 This
->lpVtbl
= &vt_IKsFilter
;
1436 This
->lpVtblKsControl
= &vt_IKsControl
;
1438 This
->Factory
= Factory
;
1439 This
->FilterFactory
= iface
;
1440 This
->FileObject
= IoStack
->FileObject
;
1441 KeInitializeMutex(&This
->ProcessingMutex
, 0);
1442 /* initialize basic header */
1443 This
->Header
.KsDevice
= &DeviceExtension
->DeviceHeader
->KsDevice
;
1444 This
->Header
.Parent
.KsFilterFactory
= iface
->lpVtbl
->GetStruct(iface
);
1445 This
->Header
.Type
= KsObjectTypeFilter
;
1446 This
->Header
.ControlMutex
= &This
->ControlMutex
;
1447 KeInitializeMutex(This
->Header
.ControlMutex
, 0);
1448 InitializeListHead(&This
->Header
.EventList
);
1449 KeInitializeSpinLock(&This
->Header
.EventListLock
);
1451 /* allocate the stream descriptors */
1452 Status
= IKsFilter_CreateDescriptors(This
, (PKSFILTER_DESCRIPTOR
)Factory
->FilterDescriptor
);
1453 if (!NT_SUCCESS(Status
))
1455 /* what can go wrong, goes wrong */
1457 FreeItem(CreateItem
);
1458 DPRINT("IKsFilter_CreateDescriptors failed with %lx\n", Status
);
1462 /* does the filter have a filter dispatch */
1463 if (Factory
->FilterDescriptor
->Dispatch
)
1465 /* does it have a create routine */
1466 if (Factory
->FilterDescriptor
->Dispatch
->Create
)
1468 /* now let driver initialize the filter instance */
1470 ASSERT(This
->Header
.KsDevice
);
1471 ASSERT(This
->Header
.KsDevice
->Started
);
1472 Status
= Factory
->FilterDescriptor
->Dispatch
->Create(&This
->Filter
, Irp
);
1474 if (!NT_SUCCESS(Status
) && Status
!= STATUS_PENDING
)
1476 /* driver failed to initialize */
1477 DPRINT1("Driver: Status %x\n", Status
);
1479 /* free filter instance */
1481 FreeItem(CreateItem
);
1487 /* now allocate the object header */
1488 Status
= KsAllocateObjectHeader((PVOID
*)&This
->ObjectHeader
, 2, CreateItem
, Irp
, &DispatchTable
);
1489 if (!NT_SUCCESS(Status
))
1491 /* failed to allocate object header */
1492 DPRINT1("Failed to allocate object header %x\n", Status
);
1497 /* initialize object header extra fields */
1498 This
->ObjectHeader
->Type
= KsObjectTypeFilter
;
1499 This
->ObjectHeader
->Unknown
= (PUNKNOWN
)&This
->lpVtbl
;
1500 This
->ObjectHeader
->ObjectType
= (PVOID
)&This
->Filter
;
1502 /* attach filter to filter factory */
1503 IKsFilter_AttachFilterToFilterFactory(This
, This
->Header
.Parent
.KsFilterFactory
);
1505 /* completed initialization */
1506 DPRINT("KspCreateFilter done %lx\n", Status
);
1516 KsFilterAcquireProcessingMutex(
1517 IN PKSFILTER Filter
)
1519 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1521 KeWaitForSingleObject(&This
->ProcessingMutex
, Executive
, KernelMode
, FALSE
, NULL
);
1530 KsFilterReleaseProcessingMutex(
1531 IN PKSFILTER Filter
)
1533 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1535 KeReleaseMutex(&This
->ProcessingMutex
, FALSE
);
1545 KsFilterAddTopologyConnections (
1546 IN PKSFILTER Filter
,
1547 IN ULONG NewConnectionsCount
,
1548 IN
const KSTOPOLOGY_CONNECTION
*const NewTopologyConnections
)
1551 KSTOPOLOGY_CONNECTION
* Connections
;
1552 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1554 Count
= This
->Filter
.Descriptor
->ConnectionsCount
+ NewConnectionsCount
;
1556 /* allocate array */
1557 Connections
= AllocateItem(NonPagedPool
, Count
* sizeof(KSTOPOLOGY_CONNECTION
));
1559 return STATUS_INSUFFICIENT_RESOURCES
;
1561 /* FIXME verify connections */
1563 if (This
->Filter
.Descriptor
->ConnectionsCount
)
1565 /* copy old connections */
1566 RtlMoveMemory(Connections
, This
->Filter
.Descriptor
->Connections
, sizeof(KSTOPOLOGY_CONNECTION
) * This
->Filter
.Descriptor
->ConnectionsCount
);
1569 /* add new connections */
1570 RtlMoveMemory((PVOID
)(Connections
+ This
->Filter
.Descriptor
->ConnectionsCount
), NewTopologyConnections
, NewConnectionsCount
);
1572 /* add the new connections */
1573 RtlMoveMemory((PVOID
)&This
->Filter
.Descriptor
->ConnectionsCount
, &Count
, sizeof(ULONG
)); /* brain-dead gcc hack */
1575 /* free old connections array */
1576 if (This
->Filter
.Descriptor
->ConnectionsCount
)
1578 FreeItem((PVOID
)This
->Filter
.Descriptor
->Connections
);
1581 /* brain-dead gcc hack */
1582 RtlMoveMemory((PVOID
)&This
->Filter
.Descriptor
->Connections
, Connections
, sizeof(KSTOPOLOGY_CONNECTION
*));
1584 return STATUS_SUCCESS
;
1593 KsFilterAttemptProcessing(
1594 IN PKSFILTER Filter
,
1595 IN BOOLEAN Asynchronous
)
1606 KsFilterCreateNode (
1607 IN PKSFILTER Filter
,
1608 IN
const KSNODE_DESCRIPTOR
*const NodeDescriptor
,
1612 return STATUS_NOT_IMPLEMENTED
;
1621 KsFilterCreatePinFactory (
1622 IN PKSFILTER Filter
,
1623 IN
const KSPIN_DESCRIPTOR_EX
*const InPinDescriptor
,
1628 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1630 DPRINT("KsFilterCreatePinFactory\n");
1632 /* calculate new count */
1633 Count
= This
->PinDescriptorCount
+ 1;
1636 ASSERT(This
->Filter
.Descriptor
->PinDescriptorSize
== sizeof(KSPIN_DESCRIPTOR_EX
));
1638 /* allocate pin descriptors ex array */
1639 Status
= _KsEdit(This
->Filter
.Bag
, (PVOID
*)&This
->PinDescriptorsEx
, Count
* sizeof(KSPIN_DESCRIPTOR_EX
), This
->PinDescriptorCount
* sizeof(KSPIN_DESCRIPTOR_EX
), 0);
1640 if (!NT_SUCCESS(Status
))
1643 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status
);
1647 /* allocate pin descriptors array */
1648 Status
= _KsEdit(This
->Filter
.Bag
, (PVOID
*)&This
->PinDescriptors
, Count
* sizeof(KSPIN_DESCRIPTOR
), This
->PinDescriptorCount
* sizeof(KSPIN_DESCRIPTOR
), 0);
1649 if (!NT_SUCCESS(Status
))
1652 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status
);
1657 /* allocate pin instance count array */
1658 Status
= _KsEdit(This
->Filter
.Bag
,(PVOID
*)&This
->PinInstanceCount
, sizeof(ULONG
) * Count
, sizeof(ULONG
) * This
->PinDescriptorCount
, 0);
1659 if (!NT_SUCCESS(Status
))
1662 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status
);
1666 /* allocate first pin array */
1667 Status
= _KsEdit(This
->Filter
.Bag
,(PVOID
*)&This
->FirstPin
, sizeof(PKSPIN
) * Count
, sizeof(PKSPIN
) * This
->PinDescriptorCount
, 0);
1668 if (!NT_SUCCESS(Status
))
1671 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status
);
1675 /* add new pin factory */
1676 RtlMoveMemory(&This
->PinDescriptorsEx
[This
->PinDescriptorCount
], InPinDescriptor
, sizeof(KSPIN_DESCRIPTOR_EX
));
1677 RtlMoveMemory(&This
->PinDescriptors
[This
->PinDescriptorCount
], &InPinDescriptor
->PinDescriptor
, sizeof(KSPIN_DESCRIPTOR
));
1680 /* allocate process pin index */
1681 Status
= _KsEdit(This
->Filter
.Bag
, (PVOID
*)&This
->ProcessPinIndex
, sizeof(KSPROCESSPIN_INDEXENTRY
) * Count
,
1682 sizeof(KSPROCESSPIN_INDEXENTRY
) * This
->PinDescriptorCount
, 0);
1684 if (!NT_SUCCESS(Status
))
1686 DPRINT("KsFilterCreatePinFactory _KsEdit failed %lx\n", Status
);
1690 /* store new pin id */
1691 *PinID
= This
->PinDescriptorCount
;
1693 /* increment pin descriptor count */
1694 This
->PinDescriptorCount
++;
1697 DPRINT("KsFilterCreatePinFactory done\n");
1698 return STATUS_SUCCESS
;
1709 IN PKSFILTER Filter
)
1721 KsFilterGetChildPinCount(
1722 IN PKSFILTER Filter
,
1725 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1727 if (PinId
>= This
->PinDescriptorCount
)
1729 /* index is out of bounds */
1732 /* return pin instance count */
1733 return This
->PinInstanceCount
[PinId
];
1742 KsFilterGetFirstChildPin(
1743 IN PKSFILTER Filter
,
1746 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1748 if (PinId
>= This
->PinDescriptorCount
)
1750 /* index is out of bounds */
1754 /* return first pin index */
1755 return This
->FirstPin
[PinId
];
1764 KsFilterRegisterPowerCallbacks(
1765 IN PKSFILTER Filter
,
1766 IN PFNKSFILTERPOWER Sleep OPTIONAL
,
1767 IN PFNKSFILTERPOWER Wake OPTIONAL
)
1769 IKsFilterImpl
* This
= (IKsFilterImpl
*)CONTAINING_RECORD(Filter
, IKsFilterImpl
, Filter
);
1771 This
->Sleep
= Sleep
;
1784 PIO_STACK_LOCATION IoStack
;
1785 PKSIOBJECT_HEADER ObjectHeader
;
1787 DPRINT("KsGetFilterFromIrp\n");
1789 /* get current irp stack location */
1790 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1793 ASSERT(IoStack
->FileObject
);
1795 /* get object header */
1796 ObjectHeader
= (PKSIOBJECT_HEADER
)IoStack
->FileObject
->FsContext2
;
1798 if (ObjectHeader
->Type
== KsObjectTypeFilter
)
1800 /* irp is targeted at the filter */
1801 return (PKSFILTER
)ObjectHeader
->ObjectType
;
1803 else if (ObjectHeader
->Type
== KsObjectTypePin
)
1805 /* irp is for a pin */
1806 return KsPinGetParentFilter((PKSPIN
)ObjectHeader
->ObjectType
);
1810 /* irp is unappropiate to retrieve a filter */