[KS]
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Sat, 10 Apr 2010 18:00:17 +0000 (18:00 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Sat, 10 Apr 2010 18:00:17 +0000 (18:00 +0000)
- 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

svn path=/trunk/; revision=46824

reactos/drivers/ksfilter/ks/filter.c
reactos/drivers/ksfilter/ks/ksfunc.h
reactos/drivers/ksfilter/ks/methods.c
reactos/drivers/ksfilter/ks/pin.c

index d5af650..bcac218 100644 (file)
@@ -778,12 +778,16 @@ IKsFilter_DispatchDeviceIoControl(
     /* get property from input buffer */
     Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
 
-    /* sanity check */
-    ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSIDENTIFIER));
-
     /* 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);
+
     RtlStringFromGUID(&Property->Set, &GuidString);
     DPRINT("IKsFilter_DispatchDeviceIoControl property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
     RtlFreeUnicodeString(&GuidString);
@@ -794,7 +798,7 @@ IKsFilter_DispatchDeviceIoControl(
         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 @@ IKsFilter_DispatchDeviceIoControl(
         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 @@ IKsFilter_DispatchDeviceIoControl(
         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 @@ IKsFilter_CopyFilterDescriptor(
 }
 
 
-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 @@ IKsFilter_AddPin(
     {
         /* welcome first pin */
         This->FirstPin[Pin->Id] = Pin;
-        return STATUS_SUCCESS;
+        This->PinInstanceCount[Pin->Id]++;
+        return;
     }
 
     /* get first pin */
@@ -1079,8 +1099,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->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 @@ IKsFilter_DispatchCreatePin(
             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 @@ KsFilterReleaseProcessingMutex(
     KeReleaseMutex(&This->ProcessingMutex, FALSE);
 }
 
+
 /*
     @implemented
 */
index 64e2582..75d73ea 100644 (file)
@@ -122,11 +122,6 @@ KspCreatePin(
     IN PKSPIN_CONNECT Connect,
     IN KSPIN_DESCRIPTOR_EX* Descriptor);
 
-NTSTATUS
-IKsFilter_AddPin(
-    IKsFilter * Filter,
-    PKSPIN Pin);
-
 NTSTATUS
 KspAddCreateItemToList(
     OUT PLIST_ENTRY ListHead,
@@ -165,3 +160,24 @@ KspMethodHandlerWithAllocator(
     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);
+
index eed17bd..6263ce0 100644 (file)
@@ -22,9 +22,6 @@ FindMethodHandler(
 {
     ULONG Index, ItemIndex;
 
-    /* TODO */
-    ASSERT((Method->Flags & KSMETHOD_TYPE_SETSUPPORT) == 0);
-
     for(Index = 0; Index < MethodSetCount; Index++)
     {
         ASSERT(MethodSet[Index].Set);
index 682d25e..aa39c8d 100644 (file)
@@ -151,11 +151,14 @@ IKsPin_PinMasterClock(
     /* 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 @@ IKsPin_PinMasterClock(
         }
     }
 
-    /* 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,126 +1907,120 @@ IKsPin_DispatchKsStream(
     return Status;
 }
 
-
 NTSTATUS
-IKsPin_DispatchKsProperty(
-    PDEVICE_OBJECT DeviceObject,
-    PIRP Irp,
-    IKsPinImpl * This)
+NTAPI
+IKsPin_DispatchDeviceIoControl(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
 {
-    NTSTATUS Status;
-    PKSPROPERTY Property;
     PIO_STACK_LOCATION IoStack;
+    PKSIOBJECT_HEADER ObjectHeader;
+    IKsPinImpl * This;
+    NTSTATUS Status;
     UNICODE_STRING GuidString;
-    ULONG PropertySetsCount = 0, PropertyItemSize = 0;
-    const KSPROPERTY_SET* PropertySets = NULL;
+    PKSPROPERTY Property;
+    ULONG SetCount = 0;
+
+    /* get current irp stack */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
 
     /* sanity check */
-    ASSERT(This->Pin.Descriptor);
+    ASSERT(IoStack->FileObject);
+    ASSERT(IoStack->FileObject->FsContext2);
 
-    /* get current irp stack */
+    /* get the object header */
+    ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
+
+    /* locate ks pin implemention from KSPIN offset */
+    This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
+
+    /* current irp stack */
     IoStack = IoGetCurrentIrpStackLocation(Irp);
 
+    /* get property from input buffer */
+    Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
 
-    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;
-    }
+    /* 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);
 
-    /* try driver provided property sets */
-    Status = KspPropertyHandler(Irp,
-                                PropertySetsCount,
-                                PropertySets,
-                                NULL,
-                                PropertyItemSize);
 
-    if (Status != STATUS_NOT_FOUND)
+    if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_METHOD)
     {
-        /* property was handled by driver */
-        if (Status != STATUS_PENDING)
+        const KSMETHOD_SET *MethodSet = NULL;
+        ULONG MethodItemSize = 0;
+
+        /* check if the driver supports method sets */
+        if (This->Pin.Descriptor->AutomationTable->MethodSetsCount)
         {
-            Irp->IoStatus.Status = Status;
-            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            SetCount = This->Pin.Descriptor->AutomationTable->MethodSetsCount;
+            MethodSet = This->Pin.Descriptor->AutomationTable->MethodSets;
+            MethodItemSize = This->Pin.Descriptor->AutomationTable->MethodItemSize;
         }
-        return Status;
+
+        /* 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;
+        }
 
-    /* try our properties */
-    Status = KspPropertyHandler(Irp,
-                                sizeof(PinPropertySet) / sizeof(KSPROPERTY_SET),
-                                PinPropertySet,
-                                NULL,
-                                0);
+        /* 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
     {
-        /* property was handled by driver */
-        if (Status != STATUS_PENDING)
+        /* 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)
         {
-            Irp->IoStatus.Status = Status;
-            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            /* 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);
         }
-        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);
+    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);
 
-    Irp->IoStatus.Status = STATUS_NOT_FOUND;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return STATUS_NOT_FOUND;
-
-}
-
-NTSTATUS
-NTAPI
-IKsPin_DispatchDeviceIoControl(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN PIRP Irp)
-{
-    PIO_STACK_LOCATION IoStack;
-    PKSIOBJECT_HEADER ObjectHeader;
-    IKsPinImpl * This;
-
-    /* get current irp stack */
-    IoStack = IoGetCurrentIrpStackLocation(Irp);
-
-    /* sanity check */
-    ASSERT(IoStack->FileObject);
-    ASSERT(IoStack->FileObject->FsContext2);
-
-    /* get the object header */
-    ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
-
-    /* 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)
+    if (Status != STATUS_PENDING)
     {
-        /* handle ks properties */
-        return IKsPin_DispatchKsStream(DeviceObject, Irp, This);
+        Irp->IoStatus.Status = Status;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
     }
 
-    UNIMPLEMENTED;
-    Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-    return STATUS_NOT_IMPLEMENTED;
+    /* done */
+    return Status;
 }
 
 NTSTATUS
@@ -2053,9 +2047,6 @@ IKsPin_Close(
     /* 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 @@ IKsPin_Close(
             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)
         {
@@ -2079,9 +2071,6 @@ IKsPin_Close(
         }
     }
 
-    /* release filter control mutex */
-    KsFilterReleaseControl(&This->Pin);
-
     return Status;
 }
 
@@ -2228,6 +2217,7 @@ KspCreatePin(
     ULONG Index;
     ULONG FrameSize = 0;
     ULONG NumFrames = 0;
+    KSAUTOMATION_TABLE AutomationTable;
 
     /* sanity checks */
     ASSERT(Descriptor->Dispatch);
@@ -2314,6 +2304,8 @@ KspCreatePin(
     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 @@ KspCreatePin(
     /* 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 @@ KspCreatePin(
     }
 
     /* 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 @@ KspCreatePin(
     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);