Author: janderwald Date: Sat Apr 10 20:00:17 2010 New Revision: 46824
URL: http://svn.reactos.org/svn/reactos?rev=46824&view=rev Log: [KS] - Implement dispatching of enable/disable event properties for filters/pins - Add new pins to list of instantiated pins when a new pin is created - Remove pin on close and decrement instance count. Fixes instantiating pin for 2nd time - Rewrite handling of pin property/method/events - ks is now able to deliver signal statistics in XP SP3
Modified: trunk/reactos/drivers/ksfilter/ks/filter.c trunk/reactos/drivers/ksfilter/ks/ksfunc.h trunk/reactos/drivers/ksfilter/ks/methods.c trunk/reactos/drivers/ksfilter/ks/pin.c
Modified: trunk/reactos/drivers/ksfilter/ks/filter.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/ksfilter/ks/filter.... ============================================================================== --- trunk/reactos/drivers/ksfilter/ks/filter.c [iso-8859-1] (original) +++ trunk/reactos/drivers/ksfilter/ks/filter.c [iso-8859-1] Sat Apr 10 20:00:17 2010 @@ -778,11 +778,15 @@ /* 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)); - - /* get filter instance */ - FilterInstance = Filter->lpVtbl->GetStruct(Filter); + ASSERT(FilterInstance); + ASSERT(FilterInstance->Descriptor); + ASSERT(FilterInstance->Descriptor->AutomationTable);
RtlStringFromGUID(&Property->Set, &GuidString); DPRINT("IKsFilter_DispatchDeviceIoControl property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags); @@ -794,7 +798,7 @@ ULONG MethodItemSize = 0;
/* check if the driver supports method sets */ - if (FilterInstance->Descriptor->AutomationTable && FilterInstance->Descriptor->AutomationTable->MethodSetsCount) + if (FilterInstance->Descriptor->AutomationTable->MethodSetsCount) { SetCount = FilterInstance->Descriptor->AutomationTable->MethodSetsCount; MethodSet = FilterInstance->Descriptor->AutomationTable->MethodSets; @@ -810,7 +814,7 @@ ULONG PropertyItemSize = 0;
/* check if the driver supports method sets */ - if (FilterInstance->Descriptor->AutomationTable && FilterInstance->Descriptor->AutomationTable->PropertySetsCount) + if (FilterInstance->Descriptor->AutomationTable->PropertySetsCount) { SetCount = FilterInstance->Descriptor->AutomationTable->PropertySetsCount; PropertySet = FilterInstance->Descriptor->AutomationTable->PropertySets; @@ -829,8 +833,23 @@ ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT || IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT);
- Status = STATUS_NOT_FOUND; - UNIMPLEMENTED; + 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 + { + /* disable event handler */ + Status = KsDisableEvent(Irp, &This->Header.EventList, KSEVENTS_SPINLOCK, &This->Header.EventListLock); + } }
RtlStringFromGUID(&Property->Set, &GuidString); @@ -1041,14 +1060,14 @@ }
-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); @@ -1057,7 +1076,8 @@ { /* welcome first pin */ This->FirstPin[Pin->Id] = Pin; - return STATUS_SUCCESS; + This->PinInstanceCount[Pin->Id]++; + return; }
/* get first pin */ @@ -1079,8 +1099,58 @@
/* 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->PinDescriptorCount); + + /* 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); }
@@ -1129,12 +1199,6 @@ Status = KspCreatePin(DeviceObject, Irp, This->Header.KsDevice, This->FilterFactory, (IKsFilter*)&This->lpVtbl, Connect, &This->PinDescriptorsEx[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 { @@ -1471,6 +1535,7 @@ KeReleaseMutex(&This->ProcessingMutex, FALSE); }
+ /* @implemented */
Modified: trunk/reactos/drivers/ksfilter/ks/ksfunc.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/ksfilter/ks/ksfunc.... ============================================================================== --- trunk/reactos/drivers/ksfilter/ks/ksfunc.h [iso-8859-1] (original) +++ trunk/reactos/drivers/ksfilter/ks/ksfunc.h [iso-8859-1] Sat Apr 10 20:00:17 2010 @@ -123,11 +123,6 @@ IN KSPIN_DESCRIPTOR_EX* Descriptor);
NTSTATUS -IKsFilter_AddPin( - IKsFilter * Filter, - PKSPIN Pin); - -NTSTATUS KspAddCreateItemToList( OUT PLIST_ENTRY ListHead, IN ULONG ItemsCount, @@ -165,3 +160,24 @@ IN PFNKSALLOCATOR Allocator OPTIONAL, IN ULONG MethodItemSize OPTIONAL);
+VOID +IKsFilter_AddPin( + PKSFILTER Filter, + PKSPIN Pin); + +VOID +IKsFilter_RemovePin( + PKSFILTER Filter, + PKSPIN Pin); + +NTSTATUS +KspEnableEvent( + IN PIRP Irp, + IN ULONG EventSetsCount, + IN PKSEVENT_SET EventSet, + IN OUT PLIST_ENTRY EventsList OPTIONAL, + IN KSEVENTS_LOCKTYPE EventsFlags OPTIONAL, + IN PVOID EventsLock OPTIONAL, + IN PFNKSALLOCATOR Allocator OPTIONAL, + IN ULONG EventItemSize OPTIONAL); +
Modified: trunk/reactos/drivers/ksfilter/ks/methods.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/ksfilter/ks/methods... ============================================================================== --- trunk/reactos/drivers/ksfilter/ks/methods.c [iso-8859-1] (original) +++ trunk/reactos/drivers/ksfilter/ks/methods.c [iso-8859-1] Sat Apr 10 20:00:17 2010 @@ -21,9 +21,6 @@ OUT PKSMETHOD_SET * Set) { ULONG Index, ItemIndex; - - /* TODO */ - ASSERT((Method->Flags & KSMETHOD_TYPE_SETSUPPORT) == 0);
for(Index = 0; Index < MethodSetCount; Index++) {
Modified: trunk/reactos/drivers/ksfilter/ks/pin.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/ksfilter/ks/pin.c?r... ============================================================================== --- trunk/reactos/drivers/ksfilter/ks/pin.c [iso-8859-1] (original) +++ trunk/reactos/drivers/ksfilter/ks/pin.c [iso-8859-1] Sat Apr 10 20:00:17 2010 @@ -151,11 +151,14 @@ /* get the object header */ ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
+ /* sanity check */ + ASSERT(ObjectHeader); + /* locate ks pin implemention from KSPIN offset */ This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
- /* acquire control mutex */ - KeWaitForSingleObject(This->BasicHeader.ControlMutex, Executive, KernelMode, FALSE, NULL); + /* sanity check */ + ASSERT(This);
Handle = (PHANDLE)Data;
@@ -226,10 +229,7 @@ } }
- /* release processing mutex */ - KeReleaseMutex(This->BasicHeader.ControlMutex, FALSE); - - DPRINT("IKsPin_PinStatePropertyHandler Status %lx\n", Status); + DPRINT("IKsPin_PinMasterClock Status %lx\n", Status); return Status; }
@@ -1907,86 +1907,6 @@ return Status; }
- -NTSTATUS -IKsPin_DispatchKsProperty( - PDEVICE_OBJECT DeviceObject, - PIRP Irp, - IKsPinImpl * This) -{ - NTSTATUS Status; - PKSPROPERTY Property; - PIO_STACK_LOCATION IoStack; - UNICODE_STRING GuidString; - ULONG PropertySetsCount = 0, PropertyItemSize = 0; - const KSPROPERTY_SET* PropertySets = NULL; - - /* sanity check */ - ASSERT(This->Pin.Descriptor); - - /* get current irp stack */ - IoStack = IoGetCurrentIrpStackLocation(Irp); - - - if (This->Pin.Descriptor->AutomationTable) - { - /* use available driver property sets */ - PropertySetsCount = This->Pin.Descriptor->AutomationTable->PropertySetsCount; - PropertySets = This->Pin.Descriptor->AutomationTable->PropertySets; - PropertyItemSize = This->Pin.Descriptor->AutomationTable->PropertyItemSize; - } - - - /* try driver provided property sets */ - Status = KspPropertyHandler(Irp, - PropertySetsCount, - PropertySets, - NULL, - PropertyItemSize); - - if (Status != STATUS_NOT_FOUND) - { - /* property was handled by driver */ - if (Status != STATUS_PENDING) - { - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - } - return Status; - } - - /* try our properties */ - Status = KspPropertyHandler(Irp, - sizeof(PinPropertySet) / sizeof(KSPROPERTY_SET), - PinPropertySet, - NULL, - 0); - - if (Status != STATUS_NOT_FOUND) - { - /* property was handled by driver */ - if (Status != STATUS_PENDING) - { - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - } - return Status; - } - - /* property was not handled */ - Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer; - - RtlStringFromGUID(&Property->Set, &GuidString); - DPRINT("IKsPin_DispatchKsProperty Unhandled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags); - RtlFreeUnicodeString(&GuidString); - - Irp->IoStatus.Status = STATUS_NOT_FOUND; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return STATUS_NOT_FOUND; - -} - NTSTATUS NTAPI IKsPin_DispatchDeviceIoControl( @@ -1996,6 +1916,10 @@ PIO_STACK_LOCATION IoStack; PKSIOBJECT_HEADER ObjectHeader; IKsPinImpl * This; + NTSTATUS Status; + UNICODE_STRING GuidString; + PKSPROPERTY Property; + ULONG SetCount = 0;
/* get current irp stack */ IoStack = IoGetCurrentIrpStackLocation(Irp); @@ -2010,23 +1934,93 @@ /* locate ks pin implemention from KSPIN offset */ This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
- if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY) - { - /* handle ks properties */ - return IKsPin_DispatchKsProperty(DeviceObject, Irp, This); - } - - if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM || - IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM) - { - /* handle ks properties */ - return IKsPin_DispatchKsStream(DeviceObject, Irp, This); - } - - UNIMPLEMENTED; - Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_NOT_IMPLEMENTED; + /* current irp stack */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + /* get property from input buffer */ + Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer; + + /* sanity check */ + ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSIDENTIFIER)); + ASSERT(This->Pin.Descriptor->AutomationTable); + + RtlStringFromGUID(&Property->Set, &GuidString); + DPRINT("IKsPin_DispatchDeviceIoControl property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags); + RtlFreeUnicodeString(&GuidString); + + + if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_METHOD) + { + const KSMETHOD_SET *MethodSet = NULL; + ULONG MethodItemSize = 0; + + /* check if the driver supports method sets */ + if (This->Pin.Descriptor->AutomationTable->MethodSetsCount) + { + SetCount = This->Pin.Descriptor->AutomationTable->MethodSetsCount; + MethodSet = This->Pin.Descriptor->AutomationTable->MethodSets; + MethodItemSize = This->Pin.Descriptor->AutomationTable->MethodItemSize; + } + + /* 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 (This->Pin.Descriptor->AutomationTable->PropertySetsCount) + { + SetCount = This->Pin.Descriptor->AutomationTable->PropertySetsCount; + PropertySet = This->Pin.Descriptor->AutomationTable->PropertySets; + PropertyItemSize = This->Pin.Descriptor->AutomationTable->PropertyItemSize; + } + + /* needed for our property handlers */ + KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (KSPROPERTY_ITEM*)This; + + /* call property handler */ + Status = KspPropertyHandler(Irp, SetCount, PropertySet, NULL, PropertyItemSize); + } + else + { + /* sanity check */ + ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT || + IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT); + + if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT) + { + /* call enable event handlers */ + Status = KspEnableEvent(Irp, + This->Pin.Descriptor->AutomationTable->EventSetsCount, + (PKSEVENT_SET)This->Pin.Descriptor->AutomationTable->EventSets, + &This->BasicHeader.EventList, + KSEVENTS_SPINLOCK, + (PVOID)&This->BasicHeader.EventListLock, + NULL, + This->Pin.Descriptor->AutomationTable->EventItemSize); + } + else + { + /* disable event handler */ + Status = KsDisableEvent(Irp, &This->BasicHeader.EventList, KSEVENTS_SPINLOCK, &This->BasicHeader.EventListLock); + } + } + + RtlStringFromGUID(&Property->Set, &GuidString); + DPRINT("IKsPin_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); + + if (Status != STATUS_PENDING) + { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + + /* done */ + return Status; }
NTSTATUS @@ -2053,9 +2047,6 @@ /* locate ks pin implemention fro KSPIN offset */ This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
- /* acquire filter control mutex */ - KsFilterAcquireControl(&This->Pin); - if (This->Pin.Descriptor->Dispatch->Close) { /* call pin close routine */ @@ -2069,7 +2060,8 @@ return Status; }
- /* FIXME remove pin from filter pin list and decrement reference count */ + /* remove pin from filter pin list and decrement reference count */ + IKsFilter_RemovePin(This->Filter->lpVtbl->GetStruct(This->Filter), &This->Pin);
if (Status != STATUS_PENDING) { @@ -2078,9 +2070,6 @@ return Status; } } - - /* release filter control mutex */ - KsFilterReleaseControl(&This->Pin);
return Status; } @@ -2228,6 +2217,7 @@ ULONG Index; ULONG FrameSize = 0; ULONG NumFrames = 0; + KSAUTOMATION_TABLE AutomationTable;
/* sanity checks */ ASSERT(Descriptor->Dispatch); @@ -2314,6 +2304,8 @@ This->BasicHeader.KsDevice = KsDevice; This->BasicHeader.Type = KsObjectTypePin; This->BasicHeader.Parent.KsFilter = Filter->lpVtbl->GetStruct(Filter); + InitializeListHead(&This->BasicHeader.EventList); + KeInitializeSpinLock(&This->BasicHeader.EventListLock);
ASSERT(This->BasicHeader.Parent.KsFilter);
@@ -2350,11 +2342,43 @@ /* initialize object bag */ Device->lpVtbl->InitializeObjectBag(Device, This->Pin.Bag, NULL);
+ /* allocate pin descriptor */ + This->Pin.Descriptor = AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR_EX)); + if (!This->Pin.Descriptor) + { + /* not enough memory */ + KsFreeObjectBag(This->Pin.Bag); + FreeItem(This); + FreeItem(CreateItem); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* copy pin descriptor */ + RtlMoveMemory((PVOID)This->Pin.Descriptor, Descriptor, sizeof(KSPIN_DESCRIPTOR_EX)); + + /* initialize automation table */ + RtlZeroMemory(&AutomationTable, sizeof(KSAUTOMATION_TABLE)); + + AutomationTable.PropertyItemSize = sizeof(KSPROPERTY_ITEM); + AutomationTable.PropertySets = PinPropertySet; + AutomationTable.PropertySetsCount = sizeof(PinPropertySet) / sizeof(KSPROPERTY_SET); + + /* merge in pin property sets */ + Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&This->Pin.Descriptor->AutomationTable, (PKSAUTOMATION_TABLE)Descriptor->AutomationTable, &AutomationTable, This->Pin.Bag); + + if (!NT_SUCCESS(Status)) + { + /* not enough memory */ + KsFreeObjectBag(This->Pin.Bag); + FreeItem(This); + FreeItem(CreateItem); + return Status; + } + /* get format */ DataFormat = (PKSDATAFORMAT)(Connect + 1);
/* initialize pin descriptor */ - This->Pin.Descriptor = Descriptor; This->Pin.Context = NULL; This->Pin.Id = Connect->PinId; This->Pin.Communication = Descriptor->PinDescriptor.Communication; @@ -2482,7 +2506,7 @@ }
/* FIXME add pin instance to filter instance */ - + IKsFilter_AddPin(Filter->lpVtbl->GetStruct(Filter), &This->Pin);
if (Descriptor->Dispatch && Descriptor->Dispatch->SetDataFormat) { @@ -2505,6 +2529,7 @@ if (!NT_SUCCESS(Status) && Status != STATUS_PENDING) { /* failed to create pin, release resources */ + IKsFilter_RemovePin(Filter->lpVtbl->GetStruct(Filter), &This->Pin); KsFreeObjectHeader((KSOBJECT_HEADER)This->ObjectHeader); KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag); FreeItem(This);