X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=drivers%2Fksfilter%2Fks%2Ffilter.c;h=6c80bf9f0c3fa2e52726b2f70769367b739f28bb;hp=5d06ca2f49d7b3ac903f5cc7cbb1073cb94120f3;hb=3c6ed75839ee99c0d27bbc4e5a3056acded1d8be;hpb=e06395dacf13fcf1bb819dcc714ca050f10e9941 diff --git a/drivers/ksfilter/ks/filter.c b/drivers/ksfilter/ks/filter.c index 5d06ca2f49d..6c80bf9f0c3 100644 --- a/drivers/ksfilter/ks/filter.c +++ b/drivers/ksfilter/ks/filter.c @@ -14,27 +14,28 @@ typedef struct KSBASIC_HEADER Header; KSFILTER Filter; - IKsFilterVtbl *lpVtbl; IKsControlVtbl *lpVtblKsControl; IKsFilterFactory * FilterFactory; + IKsProcessingObjectVtbl * lpVtblKsProcessingObject; LONG ref; PKSIOBJECT_HEADER ObjectHeader; KSTOPOLOGY Topology; - KSPIN_DESCRIPTOR_EX * PinDescriptorsEx; - KSPIN_DESCRIPTOR * PinDescriptors; - ULONG PinDescriptorCount; PKSFILTERFACTORY Factory; PFILE_OBJECT FileObject; + KMUTEX ControlMutex; KMUTEX ProcessingMutex; + PKSWORKER Worker; + WORK_QUEUE_ITEM WorkItem; + KSGATE Gate; PFNKSFILTERPOWER Sleep; PFNKSFILTERPOWER Wake; ULONG *PinInstanceCount; PKSPIN * FirstPin; - KSPROCESSPIN_INDEXENTRY ProcessPinIndex; + PKSPROCESSPIN_INDEXENTRY ProcessPinIndex; }IKsFilterImpl; @@ -43,9 +44,17 @@ const GUID IID_IKsFilter = {0x3ef6ee44L, 0x0D41, 0x11d2, {0xbe, 0xDA, 0x00, 0xc const GUID KSPROPSETID_Topology = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; const GUID KSPROPSETID_Pin = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}}; +VOID +IKsFilter_RemoveFilterFromFilterFactory( + IKsFilterImpl * This, + PKSFILTERFACTORY FilterFactory); + +NTSTATUS NTAPI FilterTopologyPropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); +NTSTATUS NTAPI FilterPinPropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); -DEFINE_KSPROPERTY_TOPOLOGYSET(IKsFilterTopologySet, KspTopologyPropertyHandler); -DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(IKsFilterPinSet, KspPinPropertyHandler, KspPinPropertyHandler, KspPinPropertyHandler); + +DEFINE_KSPROPERTY_TOPOLOGYSET(IKsFilterTopologySet, FilterTopologyPropertyHandler); +DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(IKsFilterPinSet, FilterPinPropertyHandler, FilterPinPropertyHandler, FilterPinPropertyHandler); KSPROPERTY_SET FilterPropertySet[] = { @@ -65,6 +74,196 @@ KSPROPERTY_SET FilterPropertySet[] = } }; +NTSTATUS +NTAPI +IKsProcessingObject_fnQueryInterface( + IKsProcessingObject * iface, + IN REFIID refiid, + OUT PVOID* Output) +{ + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject); + + if (IsEqualGUIDAligned(refiid, &IID_IUnknown)) + { + *Output = &This->Header.OuterUnknown; + _InterlockedIncrement(&This->ref); + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; +} + +ULONG +NTAPI +IKsProcessingObject_fnAddRef( + IKsProcessingObject * iface) +{ + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject); + + return InterlockedIncrement(&This->ref); +} + +ULONG +NTAPI +IKsProcessingObject_fnRelease( + IKsProcessingObject * iface) +{ + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject); + + InterlockedDecrement(&This->ref); + + /* Return new reference count */ + return This->ref; +} + +VOID +NTAPI +IKsProcessingObject_fnProcessingObjectWork( + IKsProcessingObject * iface) +{ + NTSTATUS Status; + LARGE_INTEGER TimeOut; + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject); + + DPRINT1("processing object\n"); + /* first check if running at passive level */ + if (KeGetCurrentIrql() == PASSIVE_LEVEL) + { + /* acquire processing mutex */ + KeWaitForSingleObject(&This->ControlMutex, Executive, KernelMode, FALSE, NULL); + } + else + { + /* dispatch level processing */ + if (KeReadStateMutex(&This->ControlMutex) == 0) + { + /* some thread was faster */ + DPRINT1("processing object too slow\n"); + return; + } + + /* acquire processing mutex */ + TimeOut.QuadPart = 0LL; + Status = KeWaitForSingleObject(&This->ControlMutex, Executive, KernelMode, FALSE, &TimeOut); + + if (Status == STATUS_TIMEOUT) + { + /* some thread was faster */ + DPRINT1("processing object too slow\n"); + return; + } + } + + do + { + + /* check if the and-gate has been enabled again */ + if (&This->Gate.Count != 0) + { + /* gate is open */ +DPRINT1("processing object gate open\n"); + break; + } + + DPRINT1("IKsProcessingObject_fnProcessingObjectWork not implemented\n"); + ASSERT(0); + + }while(TRUE); + + /* release process mutex */ + KeReleaseMutex(&This->ProcessingMutex, FALSE); +} + +PKSGATE +NTAPI +IKsProcessingObject_fnGetAndGate( + IKsProcessingObject * iface) +{ + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject); + + /* return and gate */ + return &This->Gate; +} + +VOID +NTAPI +IKsProcessingObject_fnProcess( + IKsProcessingObject * iface, + IN BOOLEAN Asynchronous) +{ + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject); + + /* should the action be asynchronous */ + if (Asynchronous) + { + /* queue work item */ + KsQueueWorkItem(This->Worker, &This->WorkItem); +DPRINT1("queueing\n"); + /* done */ + return; + } + + /* does the filter require explicit deferred processing */ + if ((This->Filter.Descriptor->Flags & (KSFILTER_FLAG_DISPATCH_LEVEL_PROCESSING | KSFILTER_FLAG_CRITICAL_PROCESSING | KSFILTER_FLAG_HYPERCRITICAL_PROCESSING)) && + KeGetCurrentIrql() > PASSIVE_LEVEL) + { + /* queue work item */ + KsQueueWorkItem(This->Worker, &This->WorkItem); +DPRINT1("queueing\n"); + /* done */ + return; + } +DPRINT1("invoke\n"); + /* call worker routine directly */ + iface->lpVtbl->ProcessingObjectWork(iface); +} + +VOID +NTAPI +IKsProcessingObject_fnReset( + IKsProcessingObject * iface) +{ + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject); + + /* acquire processing mutex */ + KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL); + + /* check if the filter supports dispatch routines */ + if (This->Filter.Descriptor->Dispatch) + { + /* has the filter a reset routine */ + if (This->Filter.Descriptor->Dispatch->Reset) + { + /* reset filter */ + This->Filter.Descriptor->Dispatch->Reset(&This->Filter); + } + } + + /* release process mutex */ + KeReleaseMutex(&This->ProcessingMutex, FALSE); +} + +VOID +NTAPI +IKsProcessingObject_fnTriggerNotification( + IKsProcessingObject * iface) +{ + +} + +static IKsProcessingObjectVtbl vt_IKsProcessingObject = +{ + IKsProcessingObject_fnQueryInterface, + IKsProcessingObject_fnAddRef, + IKsProcessingObject_fnRelease, + IKsProcessingObject_fnProcessingObjectWork, + IKsProcessingObject_fnGetAndGate, + IKsProcessingObject_fnProcess, + IKsProcessingObject_fnReset, + IKsProcessingObject_fnTriggerNotification +}; + + +//--------------------------------------------------------------------------------------------------------- NTSTATUS NTAPI IKsControl_fnQueryInterface( @@ -76,7 +275,7 @@ IKsControl_fnQueryInterface( if (IsEqualGUIDAligned(refiid, &IID_IUnknown)) { - *Output = &This->lpVtbl; + *Output = &This->Header.OuterUnknown; _InterlockedIncrement(&This->ref); return STATUS_SUCCESS; } @@ -179,12 +378,13 @@ IKsFilter_fnQueryInterface( IN REFIID refiid, OUT PVOID* Output) { - IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtbl); + NTSTATUS Status; + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown); if (IsEqualGUIDAligned(refiid, &IID_IUnknown) || IsEqualGUIDAligned(refiid, &IID_IKsFilter)) { - *Output = &This->lpVtbl; + *Output = &This->Header.OuterUnknown; _InterlockedIncrement(&This->ref); return STATUS_SUCCESS; } @@ -195,7 +395,20 @@ IKsFilter_fnQueryInterface( return STATUS_SUCCESS; } - return STATUS_UNSUCCESSFUL; + if (This->Header.ClientAggregate) + { + /* using client aggregate */ + Status = This->Header.ClientAggregate->lpVtbl->QueryInterface(This->Header.ClientAggregate, refiid, Output); + + if (NT_SUCCESS(Status)) + { + /* client aggregate supports interface */ + return Status; + } + } + + DPRINT("IKsFilter_fnQueryInterface no interface\n"); + return STATUS_NOT_SUPPORTED; } ULONG @@ -203,7 +416,7 @@ NTAPI IKsFilter_fnAddRef( IKsFilter * iface) { - IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtbl); + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown); return InterlockedIncrement(&This->ref); } @@ -213,7 +426,7 @@ NTAPI IKsFilter_fnRelease( IKsFilter * iface) { - IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtbl); + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown); InterlockedDecrement(&This->ref); @@ -232,7 +445,7 @@ NTAPI IKsFilter_fnGetStruct( IKsFilter * iface) { - IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtbl); + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown); return &This->Filter; } @@ -289,23 +502,25 @@ IKsFilter_fnAddProcessPin( IN PKSPROCESSPIN ProcessPin) { NTSTATUS Status; - IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtbl); + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown); /* first acquire processing mutex */ KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL); - /* edit process pin descriptor */ - Status = _KsEdit(This->Filter.Bag, - (PVOID*)&This->ProcessPinIndex.Pins, - (This->ProcessPinIndex.Count + 1) * sizeof(PKSPROCESSPIN), - (This->ProcessPinIndex.Count) * sizeof(PKSPROCESSPIN), + /* sanity check */ + ASSERT(This->Filter.Descriptor->PinDescriptorsCount > ProcessPin->Pin->Id); + + /* allocate new process pin array */ + Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex[ProcessPin->Pin->Id].Pins, + (This->Filter.Descriptor->PinDescriptorsCount + 1) * sizeof(PKSPROCESSPIN), + This->Filter.Descriptor->PinDescriptorsCount * sizeof(PKSPROCESSPIN), 0); if (NT_SUCCESS(Status)) { - /* add new process pin */ - This->ProcessPinIndex.Pins[This->ProcessPinIndex.Count] = ProcessPin; - This->ProcessPinIndex.Count++; + /* store process pin */ + This->ProcessPinIndex[ProcessPin->Pin->Id].Pins[This->ProcessPinIndex[ProcessPin->Pin->Id].Count] = ProcessPin; + This->ProcessPinIndex[ProcessPin->Pin->Id].Count++; } /* release process mutex */ @@ -321,25 +536,39 @@ IKsFilter_fnRemoveProcessPin( IN PKSPROCESSPIN ProcessPin) { ULONG Index; - IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtbl); + ULONG Count; + PKSPROCESSPIN * Pins; + + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown); /* first acquire processing mutex */ KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL); - /* iterate through process pin index array and search for the process pin to be removed */ - for(Index = 0; Index < This->ProcessPinIndex.Count; Index++) + /* sanity check */ + ASSERT(ProcessPin->Pin); + ASSERT(ProcessPin->Pin->Id); + + Count = This->ProcessPinIndex[ProcessPin->Pin->Id].Count; + Pins = This->ProcessPinIndex[ProcessPin->Pin->Id].Pins; + + /* search for current process pin */ + for(Index = 0; Index < Count; Index++) { - if (This->ProcessPinIndex.Pins[Index] == ProcessPin) + if (Pins[Index] == ProcessPin) { - /* found process pin */ - if (Index + 1 < This->ProcessPinIndex.Count) - { - /* erase entry */ - RtlMoveMemory(&This->ProcessPinIndex.Pins[Index], &This->ProcessPinIndex.Pins[Index+1], This->ProcessPinIndex.Count - Index - 1); - } - /* decrement process pin count */ - This->ProcessPinIndex.Count--; + RtlMoveMemory(&Pins[Index], &Pins[Index + 1], (Count - (Index + 1)) * sizeof(PKSPROCESSPIN)); + break; } + + } + + /* decrement pin count */ + This->ProcessPinIndex[ProcessPin->Pin->Id].Count--; + + if (!This->ProcessPinIndex[ProcessPin->Pin->Id].Count) + { + /* clear entry object bag will delete it */ + This->ProcessPinIndex[ProcessPin->Pin->Id].Pins = NULL; } /* release process mutex */ @@ -394,8 +623,9 @@ NTAPI IKsFilter_fnGetProcessDispatch( IKsFilter * iface) { - UNIMPLEMENTED - return NULL; + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown); + + return This->ProcessPinIndex; } static IKsFilterVtbl vt_IKsFilter = @@ -449,7 +679,7 @@ IKsFilter_GetFilterFromIrp( Irp->IoStatus.Status = Status; /* complete and forget irp */ - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return Status; } return Status; @@ -472,13 +702,13 @@ IKsFilter_DispatchClose( return Status; /* get our real implementation */ - This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, lpVtbl); + This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Header.OuterUnknown); /* does the driver support notifications */ - if (This->Factory->FilterDescriptor && This->Factory->FilterDescriptor->Dispatch && This->Factory->FilterDescriptor->Dispatch->Close) + if (This->Filter.Descriptor && This->Filter.Descriptor->Dispatch && This->Filter.Descriptor->Dispatch->Close) { /* call driver's filter close function */ - Status = This->Factory->FilterDescriptor->Dispatch->Close(&This->Filter, Irp); + Status = This->Filter.Descriptor->Dispatch->Close(&This->Filter, Irp); } if (NT_SUCCESS(Status) && Status != STATUS_PENDING) @@ -486,10 +716,10 @@ IKsFilter_DispatchClose( /* save the result */ Irp->IoStatus.Status = Status; /* complete irp */ - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); - /* FIXME remove our instance from the filter factory */ - ASSERT(0); + /* remove our instance from the filter factory */ + IKsFilter_RemoveFilterFromFilterFactory(This, This->Factory); /* free object header */ KsFreeObjectHeader(This->ObjectHeader); @@ -499,7 +729,7 @@ IKsFilter_DispatchClose( /* complete and forget */ Irp->IoStatus.Status = Status; /* complete irp */ - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); } /* done */ @@ -517,7 +747,7 @@ KspHandlePropertyInstances( KSPIN_CINSTANCES * Instances; KSP_PIN * Pin = (KSP_PIN*)Request; - if (!This->Factory->FilterDescriptor || !This->PinDescriptorCount) + if (!This->Filter.Descriptor || !This->Filter.Descriptor->PinDescriptorsCount) { /* no filter / pin descriptor */ IoStatus->Status = STATUS_NOT_IMPLEMENTED; @@ -525,12 +755,12 @@ KspHandlePropertyInstances( } /* ignore custom structs for now */ - ASSERT(This->Factory->FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); - ASSERT(This->PinDescriptorCount > Pin->PinId); + ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); + ASSERT(This->Filter.Descriptor->PinDescriptorsCount > Pin->PinId); Instances = (KSPIN_CINSTANCES*)Data; /* max instance count */ - Instances->PossibleCount = This->PinDescriptorsEx[Pin->PinId].InstancesPossible; + Instances->PossibleCount = This->Filter.Descriptor->PinDescriptors[Pin->PinId].InstancesPossible; /* current instance count */ Instances->CurrentCount = This->PinInstanceCount[Pin->PinId]; @@ -549,7 +779,7 @@ KspHandleNecessaryPropertyInstances( PULONG Result; KSP_PIN * Pin = (KSP_PIN*)Request; - if (!This->Factory->FilterDescriptor || !This->PinDescriptorCount) + if (!This->Filter.Descriptor || !This->Filter.Descriptor->PinDescriptorsCount) { /* no filter / pin descriptor */ IoStatus->Status = STATUS_NOT_IMPLEMENTED; @@ -557,11 +787,11 @@ KspHandleNecessaryPropertyInstances( } /* ignore custom structs for now */ - ASSERT(This->Factory->FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); - ASSERT(This->PinDescriptorCount > Pin->PinId); + ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); + ASSERT(This->Filter.Descriptor->PinDescriptorsCount > Pin->PinId); Result = (PULONG)Data; - *Result = This->PinDescriptorsEx[Pin->PinId].InstancesNecessary; + *Result = This->Filter.Descriptor->PinDescriptors[Pin->PinId].InstancesNecessary; IoStatus->Information = sizeof(ULONG); IoStatus->Status = STATUS_SUCCESS; @@ -581,13 +811,23 @@ KspHandleDataIntersection( PKSDATARANGE DataRange; NTSTATUS Status = STATUS_NO_MATCH; ULONG Index, Length; + PIO_STACK_LOCATION IoStack; KSP_PIN * Pin = (KSP_PIN*)Request; + /* get stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + /* sanity check */ + ASSERT(DataLength == IoStack->Parameters.DeviceIoControl.OutputBufferLength); + /* Access parameters */ MultipleItem = (PKSMULTIPLE_ITEM)(Pin + 1); DataRange = (PKSDATARANGE)(MultipleItem + 1); - if (!This->Factory->FilterDescriptor || !This->PinDescriptorCount) + /* FIXME make sure its 64 bit aligned */ + ASSERT(((ULONG_PTR)DataRange & 0x7) == 0); + + if (!This->Filter.Descriptor || !This->Filter.Descriptor->PinDescriptorsCount) { /* no filter / pin descriptor */ IoStatus->Status = STATUS_NOT_IMPLEMENTED; @@ -595,12 +835,12 @@ KspHandleDataIntersection( } /* ignore custom structs for now */ - ASSERT(This->Factory->FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); - ASSERT(This->PinDescriptorCount > Pin->PinId); + ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); + ASSERT(This->Filter.Descriptor->PinDescriptorsCount > Pin->PinId); - if (This->PinDescriptorsEx[Pin->PinId].IntersectHandler == NULL || - This->PinDescriptors[Pin->PinId].DataRanges == NULL || - This->PinDescriptors[Pin->PinId].DataRangesCount == 0) + if (This->Filter.Descriptor->PinDescriptors[Pin->PinId].IntersectHandler == NULL || + This->Filter.Descriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges == NULL || + This->Filter.Descriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRangesCount == 0) { /* no driver supported intersect handler / no provided data ranges */ IoStatus->Status = STATUS_NOT_IMPLEMENTED; @@ -609,31 +849,65 @@ KspHandleDataIntersection( for(Index = 0; Index < MultipleItem->Count; Index++) { + UNICODE_STRING MajorFormat, SubFormat, Specifier; + /* convert the guid to string */ + RtlStringFromGUID(&DataRange->MajorFormat, &MajorFormat); + RtlStringFromGUID(&DataRange->SubFormat, &SubFormat); + RtlStringFromGUID(&DataRange->Specifier, &Specifier); + + DPRINT("KspHandleDataIntersection Index %lu PinId %lu MajorFormat %S SubFormat %S Specifier %S FormatSize %lu SampleSize %lu Align %lu Flags %lx Reserved %lx DataLength %lu\n", Index, Pin->PinId, MajorFormat.Buffer, SubFormat.Buffer, Specifier.Buffer, + DataRange->FormatSize, DataRange->SampleSize, DataRange->Alignment, DataRange->Flags, DataRange->Reserved, DataLength); + + /* FIXME implement KsPinDataIntersectionEx */ /* Call miniport's properitary handler */ - Status = This->PinDescriptorsEx[Pin->PinId].IntersectHandler(NULL, /* context */ - Irp, - Pin, - DataRange, - (PKSDATAFORMAT)This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges, - DataLength, - Data, - &Length); - - if (Status == STATUS_SUCCESS) + Status = This->Filter.Descriptor->PinDescriptors[Pin->PinId].IntersectHandler(&This->Filter, + Irp, + Pin, + DataRange, + This->Filter.Descriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges[0], /* HACK */ + DataLength, + Data, + &Length); + DPRINT("KspHandleDataIntersection Status %lx\n", Status); + + if (Status == STATUS_SUCCESS || Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) { + ASSERT(Length); IoStatus->Information = Length; break; } + DataRange = UlongToPtr(PtrToUlong(DataRange) + DataRange->FormatSize); + /* FIXME make sure its 64 bit aligned */ + ASSERT(((ULONG_PTR)DataRange & 0x7) == 0); } - IoStatus->Status = Status; return Status; } NTSTATUS NTAPI -KspPinPropertyHandler( +FilterTopologyPropertyHandler( + IN PIRP Irp, + IN PKSIDENTIFIER Request, + IN OUT PVOID Data) +{ + IKsFilterImpl * This; + + /* get filter implementation */ + This = (IKsFilterImpl*)KSPROPERTY_ITEM_IRP_STORAGE(Irp); + + /* sanity check */ + ASSERT(This); + + return KsTopologyPropertyHandler(Irp, Request, Data, &This->Topology); + +} + + +NTSTATUS +NTAPI +FilterPinPropertyHandler( IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data) @@ -645,6 +919,9 @@ KspPinPropertyHandler( /* get filter implementation */ This = (IKsFilterImpl*)KSPROPERTY_ITEM_IRP_STORAGE(Irp); + /* sanity check */ + ASSERT(This); + /* get current stack location */ IoStack = IoGetCurrentIrpStackLocation(Irp); @@ -658,8 +935,8 @@ KspPinPropertyHandler( case KSPROPERTY_PIN_COMMUNICATION: case KSPROPERTY_PIN_CATEGORY: case KSPROPERTY_PIN_NAME: - case KSPROPERTY_PIN_PROPOSEDATAFORMAT: - Status = KsPinPropertyHandler(Irp, Request, Data, This->PinDescriptorCount, This->PinDescriptors); + case KSPROPERTY_PIN_CONSTRAINEDDATARANGES: + Status = KspPinPropertyHandler(Irp, Request, Data, This->Filter.Descriptor->PinDescriptorsCount, (const KSPIN_DESCRIPTOR*)This->Filter.Descriptor->PinDescriptors, This->Filter.Descriptor->PinDescriptorSize); break; case KSPROPERTY_PIN_GLOBALCINSTANCES: Status = KspHandlePropertyInstances(&Irp->IoStatus, Request, Data, This, TRUE); @@ -674,16 +951,11 @@ KspPinPropertyHandler( case KSPROPERTY_PIN_DATAINTERSECTION: Status = KspHandleDataIntersection(Irp, &Irp->IoStatus, Request, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength, This); break; - case KSPROPERTY_PIN_PHYSICALCONNECTION: - case KSPROPERTY_PIN_CONSTRAINEDDATARANGES: - UNIMPLEMENTED - Status = STATUS_NOT_IMPLEMENTED; - break; default: UNIMPLEMENTED - Status = STATUS_UNSUCCESSFUL; + Status = STATUS_NOT_FOUND; } - DPRINT("KspPinPropertyHandler Pins %lu Request->Id %lu Status %lx\n", This->PinDescriptorCount, Request->Id, Status); + //DPRINT("KspPinPropertyHandler Pins %lu Request->Id %lu Status %lx\n", This->PinDescriptorCount, Request->Id, Status); return Status; @@ -700,6 +972,9 @@ IKsFilter_DispatchDeviceIoControl( IKsFilterImpl * This; NTSTATUS Status; PKSFILTER FilterInstance; + UNICODE_STRING GuidString; + PKSPROPERTY Property; + ULONG SetCount = 0; /* obtain filter from object header */ Status = IKsFilter_GetFilterFromIrp(Irp, &Filter); @@ -707,49 +982,100 @@ IKsFilter_DispatchDeviceIoControl( return Status; /* get our real implementation */ - This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, lpVtbl); + This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Header.OuterUnknown); /* current irp stack */ IoStack = IoGetCurrentIrpStackLocation(Irp); - if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY) + /* get property from input buffer */ + Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer; + + /* get filter instance */ + FilterInstance = Filter->lpVtbl->GetStruct(Filter); + + /* sanity check */ + ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSIDENTIFIER)); + ASSERT(FilterInstance); + ASSERT(FilterInstance->Descriptor); + ASSERT(FilterInstance->Descriptor->AutomationTable); + + /* acquire control mutex */ + KeWaitForSingleObject(This->Header.ControlMutex, Executive, KernelMode, FALSE, NULL); + + if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_METHOD) { - UNIMPLEMENTED; + const KSMETHOD_SET *MethodSet = NULL; + ULONG MethodItemSize = 0; - /* release filter interface */ - Filter->lpVtbl->Release(Filter); + /* check if the driver supports method sets */ + if (FilterInstance->Descriptor->AutomationTable->MethodSetsCount) + { + SetCount = FilterInstance->Descriptor->AutomationTable->MethodSetsCount; + MethodSet = FilterInstance->Descriptor->AutomationTable->MethodSets; + MethodItemSize = FilterInstance->Descriptor->AutomationTable->MethodItemSize; + } - /* complete and forget irp */ - Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_NOT_IMPLEMENTED; + /* call method set handler */ + Status = KspMethodHandlerWithAllocator(Irp, SetCount, MethodSet, NULL, MethodItemSize); } + else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY) + { + const KSPROPERTY_SET *PropertySet = NULL; + ULONG PropertyItemSize = 0; + + /* check if the driver supports method sets */ + if (FilterInstance->Descriptor->AutomationTable->PropertySetsCount) + { + SetCount = FilterInstance->Descriptor->AutomationTable->PropertySetsCount; + PropertySet = FilterInstance->Descriptor->AutomationTable->PropertySets; + PropertyItemSize = FilterInstance->Descriptor->AutomationTable->PropertyItemSize; + } - /* call property handler supported by ks */ - KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (KSPROPERTY_ITEM*)This; - Status = KspPropertyHandler(Irp, 2, FilterPropertySet, NULL, sizeof(KSPROPERTY_ITEM)); + /* needed for our property handlers */ + KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (KSPROPERTY_ITEM*)This; - if (Status == STATUS_NOT_FOUND) + /* call property handler */ + Status = KspPropertyHandler(Irp, SetCount, PropertySet, NULL, PropertyItemSize); + } + else { - /* get filter instance */ - FilterInstance = Filter->lpVtbl->GetStruct(Filter); + /* sanity check */ + ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT || + IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT); - /* check if the driver supports property sets */ - if (FilterInstance->Descriptor->AutomationTable && FilterInstance->Descriptor->AutomationTable->PropertySetsCount) + if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT) + { + /* call enable event handlers */ + Status = KspEnableEvent(Irp, + FilterInstance->Descriptor->AutomationTable->EventSetsCount, + (PKSEVENT_SET)FilterInstance->Descriptor->AutomationTable->EventSets, + &This->Header.EventList, + KSEVENTS_SPINLOCK, + (PVOID)&This->Header.EventListLock, + NULL, + FilterInstance->Descriptor->AutomationTable->EventItemSize); + } + else { - /* call driver's filter property handler */ - Status = KspPropertyHandler(Irp, - FilterInstance->Descriptor->AutomationTable->PropertySetsCount, - FilterInstance->Descriptor->AutomationTable->PropertySets, - NULL, - FilterInstance->Descriptor->AutomationTable->PropertyItemSize); + /* disable event handler */ + Status = KsDisableEvent(Irp, &This->Header.EventList, KSEVENTS_SPINLOCK, &This->Header.EventListLock); } } + RtlStringFromGUID(&Property->Set, &GuidString); + 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); + RtlFreeUnicodeString(&GuidString); + + /* release filter */ + Filter->lpVtbl->Release(Filter); + + /* release control mutex */ + KeReleaseMutex(This->Header.ControlMutex, FALSE); + if (Status != STATUS_PENDING) { Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); } /* done */ @@ -782,9 +1108,7 @@ IKsFilter_CreateDescriptors( /* initialize pin descriptors */ This->FirstPin = NULL; This->PinInstanceCount = NULL; - This->PinDescriptors = NULL; - This->PinDescriptorsEx = NULL; - This->PinDescriptorCount = 0; + This->ProcessPinIndex = NULL; /* initialize topology descriptor */ This->Topology.CategoriesCount = FilterDescriptor->CategoriesCount; @@ -803,18 +1127,8 @@ IKsFilter_CreateDescriptors( ASSERT(FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); /* store pin descriptors ex */ - Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinDescriptorsEx, sizeof(KSPIN_DESCRIPTOR_EX) * FilterDescriptor->PinDescriptorsCount, - sizeof(KSPIN_DESCRIPTOR_EX) * FilterDescriptor->PinDescriptorsCount, 0); - - if (!NT_SUCCESS(Status)) - { - DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status); - return Status; - } - - /* store pin descriptors */ - Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinDescriptors, sizeof(KSPIN_DESCRIPTOR) * FilterDescriptor->PinDescriptorsCount, - sizeof(KSPIN_DESCRIPTOR) * FilterDescriptor->PinDescriptorsCount, 0); + Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->Filter.Descriptor->PinDescriptors, FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount, + FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount, 0); if (!NT_SUCCESS(Status)) { @@ -822,7 +1136,7 @@ IKsFilter_CreateDescriptors( return Status; } - /* store pin instance count ex */ + /* store pin instance count */ Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinInstanceCount, sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount, sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount, 0); @@ -842,18 +1156,33 @@ IKsFilter_CreateDescriptors( return Status; } - - /* add new pin factory */ - RtlMoveMemory(This->PinDescriptorsEx, FilterDescriptor->PinDescriptors, sizeof(KSPIN_DESCRIPTOR_EX) * FilterDescriptor->PinDescriptorsCount); + RtlMoveMemory((PVOID)This->Filter.Descriptor->PinDescriptors, FilterDescriptor->PinDescriptors, FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount); + + /* allocate process pin index */ + Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex, sizeof(KSPROCESSPIN_INDEXENTRY) * FilterDescriptor->PinDescriptorsCount, + sizeof(KSPROCESSPIN_INDEXENTRY) * FilterDescriptor->PinDescriptorsCount, 0); - for(Index = 0; Index < FilterDescriptor->PinDescriptorsCount; Index++) + if (!NT_SUCCESS(Status)) { - RtlMoveMemory(&This->PinDescriptors[Index], &FilterDescriptor->PinDescriptors[Index].PinDescriptor, sizeof(KSPIN_DESCRIPTOR)); + DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status); + return Status; } - /* store new pin descriptor count */ - This->PinDescriptorCount = FilterDescriptor->PinDescriptorsCount; + } + + + if (FilterDescriptor->ConnectionsCount) + { + /* modify connections array */ + Status = _KsEdit(This->Filter.Bag, + (PVOID*)&This->Filter.Descriptor->Connections, + FilterDescriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION), + FilterDescriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION), + 0); + + This->Topology.TopologyConnections = This->Filter.Descriptor->Connections; + This->Topology.TopologyConnectionsCount = ((PKSFILTER_DESCRIPTOR)This->Filter.Descriptor)->ConnectionsCount = FilterDescriptor->ConnectionsCount; } if (FilterDescriptor->NodeDescriptorsCount) @@ -905,6 +1234,7 @@ IKsFilter_CopyFilterDescriptor( const KSFILTER_DESCRIPTOR* FilterDescriptor) { NTSTATUS Status; + KSAUTOMATION_TABLE AutomationTable; This->Filter.Descriptor = AllocateItem(NonPagedPool, sizeof(KSFILTER_DESCRIPTOR)); if (!This->Filter.Descriptor) @@ -921,27 +1251,39 @@ IKsFilter_CopyFilterDescriptor( /* copy filter descriptor fields */ RtlMoveMemory((PVOID)This->Filter.Descriptor, FilterDescriptor, sizeof(KSFILTER_DESCRIPTOR)); + /* zero automation table */ + RtlZeroMemory(&AutomationTable, sizeof(KSAUTOMATION_TABLE)); + + /* setup filter property sets */ + AutomationTable.PropertyItemSize = sizeof(KSPROPERTY_ITEM); + AutomationTable.PropertySetsCount = 2; + AutomationTable.PropertySets = FilterPropertySet; + + /* merge filter automation table */ + Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&This->Filter.Descriptor->AutomationTable, (PKSAUTOMATION_TABLE)FilterDescriptor->AutomationTable, &AutomationTable, This->Filter.Bag); + return Status; } -NTSTATUS +VOID IKsFilter_AddPin( - IKsFilter * Filter, + PKSFILTER Filter, PKSPIN Pin) { PKSPIN NextPin, CurPin; PKSBASIC_HEADER BasicHeader; - IKsFilterImpl * This = (IKsFilterImpl*)Filter; + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter); /* sanity check */ - ASSERT(Pin->Id < This->PinDescriptorCount); + ASSERT(Pin->Id < This->Filter.Descriptor->PinDescriptorsCount); if (This->FirstPin[Pin->Id] == NULL) { /* welcome first pin */ This->FirstPin[Pin->Id] = Pin; - return STATUS_SUCCESS; + This->PinInstanceCount[Pin->Id]++; + return; } /* get first pin */ @@ -963,8 +1305,58 @@ IKsFilter_AddPin( /* store pin */ BasicHeader->Next.Pin = Pin; +} - return STATUS_SUCCESS; +VOID +IKsFilter_RemovePin( + PKSFILTER Filter, + PKSPIN Pin) +{ + PKSPIN NextPin, CurPin, LastPin; + PKSBASIC_HEADER BasicHeader; + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter); + + /* sanity check */ + ASSERT(Pin->Id < This->Filter.Descriptor->PinDescriptorsCount); + + /* get first pin */ + CurPin = This->FirstPin[Pin->Id]; + + LastPin = NULL; + do + { + /* get next instantiated pin */ + NextPin = KsPinGetNextSiblingPin(CurPin); + + if (CurPin == Pin) + { + if (LastPin) + { + /* get basic header of last pin */ + BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)LastPin - sizeof(KSBASIC_HEADER)); + + BasicHeader->Next.Pin = NextPin; + } + else + { + /* erase last pin */ + This->FirstPin[Pin->Id] = NextPin; + } + /* decrement pin instance count */ + This->PinInstanceCount[Pin->Id]--; + return; + } + + if (!NextPin) + break; + + LastPin = CurPin; + NextPin = CurPin; + + }while(NextPin != NULL); + + /* pin not found */ + ASSERT(0); } @@ -991,51 +1383,45 @@ IKsFilter_DispatchCreatePin( ASSERT(This->Header.Type == KsObjectTypeFilter); /* acquire control mutex */ - KeWaitForSingleObject(&This->Header.ControlMutex, Executive, KernelMode, FALSE, NULL); + KeWaitForSingleObject(This->Header.ControlMutex, Executive, KernelMode, FALSE, NULL); /* now validate the connect request */ - Status = KsValidateConnectRequest(Irp, This->PinDescriptorCount, This->PinDescriptors, &Connect); + Status = KspValidateConnectRequest(Irp, This->Filter.Descriptor->PinDescriptorsCount, (PVOID)This->Filter.Descriptor->PinDescriptors, This->Filter.Descriptor->PinDescriptorSize, &Connect); DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest %lx\n", Status); if (NT_SUCCESS(Status)) { /* sanity check */ - ASSERT(Connect->PinId < This->PinDescriptorCount); + ASSERT(Connect->PinId < This->Filter.Descriptor->PinDescriptorsCount); DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest PinId %lu CurrentInstanceCount %lu MaxPossible %lu\n", Connect->PinId, This->PinInstanceCount[Connect->PinId], - This->PinDescriptorsEx[Connect->PinId].InstancesPossible); + This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible); - if (This->PinInstanceCount[Connect->PinId] < This->PinDescriptorsEx[Connect->PinId].InstancesPossible) + if (This->PinInstanceCount[Connect->PinId] < This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible) { /* create the pin */ - Status = KspCreatePin(DeviceObject, Irp, This->Header.KsDevice, This->FilterFactory, (IKsFilter*)&This->lpVtbl, Connect, &This->PinDescriptorsEx[Connect->PinId]); + Status = KspCreatePin(DeviceObject, Irp, This->Header.KsDevice, This->FilterFactory, (IKsFilter*)&This->Header.OuterUnknown, Connect, (KSPIN_DESCRIPTOR_EX*)&This->Filter.Descriptor->PinDescriptors[Connect->PinId]); DPRINT("IKsFilter_DispatchCreatePin KspCreatePin %lx\n", Status); - - if (NT_SUCCESS(Status)) - { - /* successfully created pin, increment pin instance count */ - This->PinInstanceCount[Connect->PinId]++; - } } else { /* maximum instance count reached, bye-bye */ Status = STATUS_UNSUCCESSFUL; - DPRINT("IKsFilter_DispatchCreatePin MaxInstance %lu CurInstance %lu %lx\n", This->PinDescriptorsEx[Connect->PinId].InstancesPossible, This->PinInstanceCount[Connect->PinId]); + DPRINT("IKsFilter_DispatchCreatePin MaxInstance %lu CurInstance %lu %lx\n", This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible, This->PinInstanceCount[Connect->PinId]); } } /* release control mutex */ - KeReleaseMutex(&This->Header.ControlMutex, FALSE); + KeReleaseMutex(This->Header.ControlMutex, FALSE); if (Status != STATUS_PENDING) { /* complete request */ Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); } /* done */ @@ -1051,7 +1437,7 @@ IKsFilter_DispatchCreateNode( { UNIMPLEMENTED Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + CompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_UNSUCCESSFUL; } @@ -1098,12 +1484,86 @@ IKsFilter_AttachFilterToFilterFactory( /* found last entry */ break; } - }while(FilterFactory); + }while(TRUE); /* attach filter factory */ BasicHeader->Next.Filter = &This->Filter; } +VOID +IKsFilter_RemoveFilterFromFilterFactory( + IKsFilterImpl * This, + PKSFILTERFACTORY FilterFactory) +{ + PKSBASIC_HEADER BasicHeader; + PKSFILTER Filter, LastFilter; + + /* get filter factory basic header */ + BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)FilterFactory - sizeof(KSBASIC_HEADER)); + + /* sanity check */ + ASSERT(BasicHeader->Type == KsObjectTypeFilterFactory); + ASSERT(BasicHeader->FirstChild.Filter != NULL); + + + /* set to first entry */ + Filter = BasicHeader->FirstChild.Filter; + LastFilter = NULL; + + do + { + if (Filter == &This->Filter) + { + if (LastFilter) + { + /* get basic header */ + BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)LastFilter - sizeof(KSBASIC_HEADER)); + /* remove filter instance */ + BasicHeader->Next.Filter = This->Header.Next.Filter; + break; + } + else + { + /* remove filter instance */ + BasicHeader->FirstChild.Filter = This->Header.Next.Filter; + break; + } + } + + /* get basic header */ + BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Filter - sizeof(KSBASIC_HEADER)); + /* sanity check */ + ASSERT(BasicHeader->Type == KsObjectTypeFilter); + + LastFilter = Filter; + if (BasicHeader->Next.Filter) + { + /* iterate to next filter factory */ + Filter = BasicHeader->Next.Filter; + } + else + { + /* filter is not in list */ + ASSERT(0); + break; + } + }while(TRUE); +} + +VOID +NTAPI +IKsFilter_FilterCentricWorker( + IN PVOID Ctx) +{ + IKsProcessingObject * Object = (IKsProcessingObject*)Ctx; + + /* sanity check */ + ASSERT(Object); + + /* perform work */ + Object->lpVtbl->ProcessingObjectWork(Object); +} + NTSTATUS NTAPI KspCreateFilter( @@ -1125,17 +1585,27 @@ KspCreateFilter( /* get the filter factory */ Factory = iface->lpVtbl->GetStruct(iface); - if (!Factory || !Factory->FilterDescriptor || !Factory->FilterDescriptor->Dispatch || !Factory->FilterDescriptor->Dispatch->Create) + if (!Factory || !Factory->FilterDescriptor) { /* Sorry it just will not work */ return STATUS_UNSUCCESSFUL; } + if (Factory->FilterDescriptor->Flags & KSFILTER_FLAG_DENY_USERMODE_ACCESS) + { + if (Irp->RequestorMode == UserMode) + { + /* filter not accessible from user mode */ + DPRINT1("Access denied\n"); + return STATUS_UNSUCCESSFUL; + } + } + /* allocate filter instance */ This = AllocateItem(NonPagedPool, sizeof(IKsFilterImpl)); if (!This) { - DPRINT("KspCreateFilter OutOfMemory\n"); + DPRINT1("KspCreateFilter OutOfMemory\n"); return STATUS_INSUFFICIENT_RESOURCES; } @@ -1145,10 +1615,10 @@ KspCreateFilter( { /* no memory */ FreeItem(This); - DPRINT("KspCreateFilter OutOfMemory\n"); + DPRINT1("KspCreateFilter OutOfMemory\n"); return STATUS_INSUFFICIENT_RESOURCES; } - KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->lpVtblIKsDevice; + KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->BasicHeader.OuterUnknown; KsDevice->lpVtbl->InitializeObjectBag(KsDevice, (PKSIOBJECT_BAG)This->Filter.Bag, NULL); /* copy filter descriptor */ @@ -1172,7 +1642,7 @@ KspCreateFilter( /* no memory */ FreeItem(This->Filter.Bag); FreeItem(This); - DPRINT("KspCreateFilter OutOfMemory\n"); + DPRINT1("KspCreateFilter OutOfMemory\n"); return STATUS_INSUFFICIENT_RESOURCES; } @@ -1190,33 +1660,57 @@ KspCreateFilter( /* initialize filter instance */ This->ref = 1; - This->lpVtbl = &vt_IKsFilter; + This->Header.OuterUnknown = (PUNKNOWN)&vt_IKsFilter; This->lpVtblKsControl = &vt_IKsControl; + This->lpVtblKsProcessingObject = &vt_IKsProcessingObject; - This->Filter.Descriptor = Factory->FilterDescriptor; This->Factory = Factory; This->FilterFactory = iface; This->FileObject = IoStack->FileObject; KeInitializeMutex(&This->ProcessingMutex, 0); + /* initialize basic header */ This->Header.KsDevice = &DeviceExtension->DeviceHeader->KsDevice; This->Header.Parent.KsFilterFactory = iface->lpVtbl->GetStruct(iface); This->Header.Type = KsObjectTypeFilter; - KeInitializeMutex(&This->Header.ControlMutex, 0); + This->Header.ControlMutex = &This->ControlMutex; + KeInitializeMutex(This->Header.ControlMutex, 0); InitializeListHead(&This->Header.EventList); KeInitializeSpinLock(&This->Header.EventListLock); + /* initialize and gate */ + KsGateInitializeAnd(&This->Gate, NULL); + + /* FIXME initialize and gate based on pin flags */ + + /* initialize work item */ + ExInitializeWorkItem(&This->WorkItem, IKsFilter_FilterCentricWorker, (PVOID)This->lpVtblKsProcessingObject); + + /* allocate counted work item */ + Status = KsRegisterCountedWorker(HyperCriticalWorkQueue, &This->WorkItem, &This->Worker); + if (!NT_SUCCESS(Status)) + { + /* what can go wrong, goes wrong */ + DPRINT1("KsRegisterCountedWorker failed with %lx\n", Status); + FreeItem(This); + FreeItem(CreateItem); + return Status; + } + /* allocate the stream descriptors */ Status = IKsFilter_CreateDescriptors(This, (PKSFILTER_DESCRIPTOR)Factory->FilterDescriptor); if (!NT_SUCCESS(Status)) { /* what can go wrong, goes wrong */ + DPRINT1("IKsFilter_CreateDescriptors failed with %lx\n", Status); + KsUnregisterWorker(This->Worker); FreeItem(This); FreeItem(CreateItem); - DPRINT("IKsFilter_CreateDescriptors failed with %lx\n", Status); return Status; } + + /* does the filter have a filter dispatch */ if (Factory->FilterDescriptor->Dispatch) { @@ -1224,8 +1718,9 @@ KspCreateFilter( if (Factory->FilterDescriptor->Dispatch->Create) { /* now let driver initialize the filter instance */ - DPRINT("Before instantiating filter Filter %p This %p KSBASIC_HEADER %u\n", &This->Filter, This, sizeof(KSBASIC_HEADER)); + ASSERT(This->Header.KsDevice); + ASSERT(This->Header.KsDevice->Started); Status = Factory->FilterDescriptor->Dispatch->Create(&This->Filter, Irp); if (!NT_SUCCESS(Status) && Status != STATUS_PENDING) @@ -1234,6 +1729,7 @@ KspCreateFilter( DPRINT1("Driver: Status %x\n", Status); /* free filter instance */ + KsUnregisterWorker(This->Worker); FreeItem(This); FreeItem(CreateItem); return Status; @@ -1253,14 +1749,14 @@ KspCreateFilter( /* initialize object header extra fields */ This->ObjectHeader->Type = KsObjectTypeFilter; - This->ObjectHeader->Unknown = (PUNKNOWN)&This->lpVtbl; + This->ObjectHeader->Unknown = (PUNKNOWN)&This->Header.OuterUnknown; This->ObjectHeader->ObjectType = (PVOID)&This->Filter; /* attach filter to filter factory */ IKsFilter_AttachFilterToFilterFactory(This, This->Header.Parent.KsFilterFactory); /* completed initialization */ - DPRINT("KspCreateFilter done %lx\n", Status); + DPRINT1("KspCreateFilter done %lx KsDevice %p\n", Status, This->Header.KsDevice); return Status; } @@ -1292,6 +1788,7 @@ KsFilterReleaseProcessingMutex( KeReleaseMutex(&This->ProcessingMutex, FALSE); } + /* @implemented */ @@ -1304,44 +1801,46 @@ KsFilterAddTopologyConnections ( IN const KSTOPOLOGY_CONNECTION *const NewTopologyConnections) { ULONG Count; - KSTOPOLOGY_CONNECTION * Connections; + NTSTATUS Status; IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter); + DPRINT("KsFilterAddTopologyConnections\n"); + + ASSERT(This->Filter.Descriptor); Count = This->Filter.Descriptor->ConnectionsCount + NewConnectionsCount; - /* allocate array */ - Connections = AllocateItem(NonPagedPool, Count * sizeof(KSTOPOLOGY_CONNECTION)); - if (!Connections) - return STATUS_INSUFFICIENT_RESOURCES; - /* FIXME verify connections */ + /* modify connections array */ + Status = _KsEdit(This->Filter.Bag, + (PVOID*)&This->Filter.Descriptor->Connections, + Count * sizeof(KSTOPOLOGY_CONNECTION), + This->Filter.Descriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION), + 0); - if (This->Filter.Descriptor->ConnectionsCount) + if (!NT_SUCCESS(Status)) { - /* copy old connections */ - RtlMoveMemory(Connections, This->Filter.Descriptor->Connections, sizeof(KSTOPOLOGY_CONNECTION) * This->Filter.Descriptor->ConnectionsCount); + /* failed */ + DPRINT("KsFilterAddTopologyConnections KsEdit failed with %lx\n", Status); + return Status; } - /* add new connections */ - RtlMoveMemory((PVOID)(Connections + This->Filter.Descriptor->ConnectionsCount), NewTopologyConnections, NewConnectionsCount); + /* FIXME verify connections */ - /* add the new connections */ - RtlMoveMemory((PVOID)&This->Filter.Descriptor->ConnectionsCount, &Count, sizeof(ULONG)); /* brain-dead gcc hack */ + /* copy new connections */ + RtlMoveMemory((PVOID)&This->Filter.Descriptor->Connections[This->Filter.Descriptor->ConnectionsCount], + NewTopologyConnections, + NewConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION)); - /* free old connections array */ - if (This->Filter.Descriptor->ConnectionsCount) - { - FreeItem((PVOID)This->Filter.Descriptor->Connections); - } + /* update topology */ + This->Topology.TopologyConnectionsCount += NewConnectionsCount; + ((PKSFILTER_DESCRIPTOR)This->Filter.Descriptor)->ConnectionsCount += NewConnectionsCount; + This->Topology.TopologyConnections = This->Filter.Descriptor->Connections; - /* brain-dead gcc hack */ - RtlMoveMemory((PVOID)&This->Filter.Descriptor->Connections, Connections, sizeof(KSTOPOLOGY_CONNECTION*)); - - return STATUS_SUCCESS; + return Status; } /* - @unimplemented + @implemented */ KSDDKAPI VOID @@ -1350,7 +1849,21 @@ KsFilterAttemptProcessing( IN PKSFILTER Filter, IN BOOLEAN Asynchronous) { - UNIMPLEMENTED + PKSGATE Gate; + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter); + + /* get gate */ + Gate = This->lpVtblKsProcessingObject->GetAndGate((IKsProcessingObject*)This->lpVtblKsProcessingObject); + + if (!KsGateCaptureThreshold(Gate)) + { + /* filter control gate is closed */ + DPRINT1("Gate %p Closed %x\n", Gate, Gate->Count); + return; + } +DPRINT1("processing\n"); + /* try initiate processing */ + This->lpVtblKsProcessingObject->Process((IKsProcessingObject*)This->lpVtblKsProcessingObject, Asynchronous); } /* @@ -1386,13 +1899,13 @@ KsFilterCreatePinFactory ( DPRINT("KsFilterCreatePinFactory\n"); /* calculate new count */ - Count = This->PinDescriptorCount + 1; + Count = This->Filter.Descriptor->PinDescriptorsCount + 1; /* sanity check */ ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); - /* allocate pin descriptors ex array */ - Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinDescriptorsEx, Count * sizeof(KSPIN_DESCRIPTOR_EX), This->PinDescriptorCount * sizeof(KSPIN_DESCRIPTOR_EX), 0); + /* modify pin descriptors ex array */ + Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->Filter.Descriptor->PinDescriptors, Count * This->Filter.Descriptor->PinDescriptorSize, This->Filter.Descriptor->PinDescriptorsCount * This->Filter.Descriptor->PinDescriptorSize, 0); if (!NT_SUCCESS(Status)) { /* failed */ @@ -1400,8 +1913,8 @@ KsFilterCreatePinFactory ( return Status; } - /* allocate pin descriptors array */ - Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinDescriptors, Count * sizeof(KSPIN_DESCRIPTOR), This->PinDescriptorCount * sizeof(KSPIN_DESCRIPTOR), 0); + /* modify pin instance count array */ + Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->PinInstanceCount, sizeof(ULONG) * Count, sizeof(ULONG) * This->Filter.Descriptor->PinDescriptorsCount, 0); if (!NT_SUCCESS(Status)) { /* failed */ @@ -1409,9 +1922,8 @@ KsFilterCreatePinFactory ( return Status; } - - /* allocate pin instance count array */ - Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->PinInstanceCount, sizeof(ULONG) * Count, sizeof(ULONG) * This->PinDescriptorCount, 0); + /* modify first pin array */ + Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->FirstPin, sizeof(PKSPIN) * Count, sizeof(PKSPIN) * This->Filter.Descriptor->PinDescriptorsCount, 0); if (!NT_SUCCESS(Status)) { /* failed */ @@ -1419,24 +1931,24 @@ KsFilterCreatePinFactory ( return Status; } - /* allocate first pin array */ - Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->FirstPin, sizeof(PKSPIN) * Count, sizeof(PKSPIN) * This->PinDescriptorCount, 0); + /* add new pin factory */ + RtlMoveMemory((PVOID)&This->Filter.Descriptor->PinDescriptors[This->Filter.Descriptor->PinDescriptorsCount], InPinDescriptor, sizeof(KSPIN_DESCRIPTOR_EX)); + + /* allocate process pin index */ + Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex, sizeof(KSPROCESSPIN_INDEXENTRY) * Count, + sizeof(KSPROCESSPIN_INDEXENTRY) * This->Filter.Descriptor->PinDescriptorsCount, 0); + if (!NT_SUCCESS(Status)) { - /* failed */ - DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status); + DPRINT("KsFilterCreatePinFactory _KsEdit failed %lx\n", Status); return Status; } - /* add new pin factory */ - RtlMoveMemory(&This->PinDescriptorsEx[This->PinDescriptorCount], InPinDescriptor, sizeof(KSPIN_DESCRIPTOR_EX)); - RtlMoveMemory(&This->PinDescriptors[This->PinDescriptorCount], &InPinDescriptor->PinDescriptor, sizeof(KSPIN_DESCRIPTOR)); - /* store new pin id */ - *PinID = This->PinDescriptorCount; + *PinID = This->Filter.Descriptor->PinDescriptorsCount; /* increment pin descriptor count */ - This->PinDescriptorCount++; + ((PKSFILTER_DESCRIPTOR)This->Filter.Descriptor)->PinDescriptorsCount++; DPRINT("KsFilterCreatePinFactory done\n"); @@ -1453,8 +1965,10 @@ NTAPI KsFilterGetAndGate( IN PKSFILTER Filter) { - UNIMPLEMENTED - return NULL; + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter); + + /* return and-gate */ + return &This->Gate; } /* @@ -1469,7 +1983,7 @@ KsFilterGetChildPinCount( { IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter); - if (PinId >= This->PinDescriptorCount) + if (PinId >= This->Filter.Descriptor->PinDescriptorsCount) { /* index is out of bounds */ return 0; @@ -1490,7 +2004,7 @@ KsFilterGetFirstChildPin( { IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter); - if (PinId >= This->PinDescriptorCount) + if (PinId >= This->Filter.Descriptor->PinDescriptorsCount) { /* index is out of bounds */ return NULL; @@ -1529,6 +2043,8 @@ KsGetFilterFromIrp( PIO_STACK_LOCATION IoStack; PKSIOBJECT_HEADER ObjectHeader; + DPRINT("KsGetFilterFromIrp\n"); + /* get current irp stack location */ IoStack = IoGetCurrentIrpStackLocation(Irp);