[AUDIO-BRINGUP]
[reactos.git] / drivers / ksfilter / ks / filter.c
index 7a8e5b2..6c80bf9 100644 (file)
@@ -14,26 +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 * 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;
 
@@ -42,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[] =
 {
@@ -64,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(
@@ -75,7 +275,7 @@ IKsControl_fnQueryInterface(
 
     if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
     {
-        *Output = &This->lpVtbl;
+        *Output = &This->Header.OuterUnknown;
         _InterlockedIncrement(&This->ref);
         return STATUS_SUCCESS;
     }
@@ -178,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;
     }
@@ -194,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
@@ -202,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);
 }
@@ -212,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);
 
@@ -231,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;
 }
@@ -287,43 +501,32 @@ IKsFilter_fnAddProcessPin(
     IKsFilter * iface,
     IN PKSPROCESSPIN ProcessPin)
 {
-    PKSPROCESSPIN *Pins;
-    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtbl);
+    NTSTATUS Status;
+    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
 
     /* first acquire processing mutex */
     KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
 
-    /* allocate new pins array */
-    Pins = AllocateItem(NonPagedPool, sizeof(PKSPROCESSPIN) * (This->ProcessPinIndex.Count + 1));
-
-    /* check if allocation succeeded */
-    if (Pins)
-    {
-        if (This->ProcessPinIndex.Count)
-        {
-            /* copy old pin index */
-            RtlMoveMemory(Pins, This->ProcessPinIndex.Pins, sizeof(PKSPROCESSPIN) * This->ProcessPinIndex.Count);
-        }
-
-        /* add new process pin */
-        Pins[This->ProcessPinIndex.Count] = ProcessPin;
+    /* sanity check */
+    ASSERT(This->Filter.Descriptor->PinDescriptorsCount > ProcessPin->Pin->Id);
 
-        /* free old process pin */
-        FreeItem(This->ProcessPinIndex.Pins);
+    /* 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);
 
-        /* store new process pin index */
-        This->ProcessPinIndex.Pins = Pins;
-        This->ProcessPinIndex.Count++;
+    if (NT_SUCCESS(Status))
+    {
+        /* 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 */
     KeReleaseMutex(&This->ProcessingMutex, FALSE);
 
-    if (Pins)
-        return STATUS_SUCCESS;
-    else
-        return STATUS_INSUFFICIENT_RESOURCES;
-
+    return Status;
 }
 
 NTSTATUS
@@ -333,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 */
@@ -406,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 =
@@ -461,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;
@@ -484,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)
@@ -498,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);
@@ -511,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 */
@@ -529,7 +747,7 @@ KspHandlePropertyInstances(
     KSPIN_CINSTANCES * Instances;
     KSP_PIN * Pin = (KSP_PIN*)Request;
 
-    if (!This->Factory->FilterDescriptor || !This->Factory->FilterDescriptor->PinDescriptorsCount)
+    if (!This->Filter.Descriptor || !This->Filter.Descriptor->PinDescriptorsCount)
     {
         /* no filter / pin descriptor */
         IoStatus->Status = STATUS_NOT_IMPLEMENTED;
@@ -537,12 +755,12 @@ KspHandlePropertyInstances(
     }
 
     /* ignore custom structs for now */
-    ASSERT(This->Factory->FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); 
-    ASSERT(This->Factory->FilterDescriptor->PinDescriptorsCount > 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->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].InstancesPossible;
+    Instances->PossibleCount = This->Filter.Descriptor->PinDescriptors[Pin->PinId].InstancesPossible;
     /* current instance count */
     Instances->CurrentCount = This->PinInstanceCount[Pin->PinId];
 
@@ -561,7 +779,7 @@ KspHandleNecessaryPropertyInstances(
     PULONG Result;
     KSP_PIN * Pin = (KSP_PIN*)Request;
 
-    if (!This->Factory->FilterDescriptor || !This->Factory->FilterDescriptor->PinDescriptorsCount)
+    if (!This->Filter.Descriptor || !This->Filter.Descriptor->PinDescriptorsCount)
     {
         /* no filter / pin descriptor */
         IoStatus->Status = STATUS_NOT_IMPLEMENTED;
@@ -569,11 +787,11 @@ KspHandleNecessaryPropertyInstances(
     }
 
     /* ignore custom structs for now */
-    ASSERT(This->Factory->FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); 
-    ASSERT(This->Factory->FilterDescriptor->PinDescriptorsCount > Pin->PinId);
+    ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); 
+    ASSERT(This->Filter.Descriptor->PinDescriptorsCount > Pin->PinId);
 
     Result = (PULONG)Data;
-    *Result = This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].InstancesNecessary;
+    *Result = This->Filter.Descriptor->PinDescriptors[Pin->PinId].InstancesNecessary;
 
     IoStatus->Information = sizeof(ULONG);
     IoStatus->Status = STATUS_SUCCESS;
@@ -593,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->Factory->FilterDescriptor->PinDescriptorsCount)
+    /* 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;
@@ -607,12 +835,12 @@ KspHandleDataIntersection(
     }
 
     /* ignore custom structs for now */
-    ASSERT(This->Factory->FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); 
-    ASSERT(This->Factory->FilterDescriptor->PinDescriptorsCount > Pin->PinId);
+    ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); 
+    ASSERT(This->Filter.Descriptor->PinDescriptorsCount > Pin->PinId);
 
-    if (This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].IntersectHandler == NULL ||
-        This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges == NULL ||
-        This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].PinDescriptor.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;
@@ -621,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->Factory->FilterDescriptor->PinDescriptors[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)
@@ -657,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);
 
@@ -670,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);
@@ -686,15 +951,12 @@ 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);
+
 
     return Status;
 }
@@ -710,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);
@@ -717,46 +982,101 @@ 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;
 
-    /* call property handler supported by ks */
-    Status = KspPropertyHandler(Irp, 2, FilterPropertySet, NULL, sizeof(KSPROPERTY_ITEM));
+        /* 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;
+        }
+
+        /* 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 driver's filter property handler */
-            Status = KspPropertyHandler(Irp, 
-                                        FilterInstance->Descriptor->AutomationTable->PropertySetsCount,
-                                        FilterInstance->Descriptor->AutomationTable->PropertySets, 
-                                        NULL,
-                                        FilterInstance->Descriptor->AutomationTable->PropertyItemSize);
+            /* 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);
         }
     }
 
-    Irp->IoStatus.Status = Status;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    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;
+        CompleteRequest(Irp, IO_NO_INCREMENT);
+    }
 
     /* done */
     return Status;
@@ -783,75 +1103,127 @@ IKsFilter_CreateDescriptors(
     KSFILTER_DESCRIPTOR* FilterDescriptor)
 {
     ULONG Index = 0;
+    NTSTATUS Status;
 
     /* initialize pin descriptors */
+    This->FirstPin = NULL;
+    This->PinInstanceCount = NULL;
+    This->ProcessPinIndex = NULL;
+
+    /* initialize topology descriptor */
+    This->Topology.CategoriesCount = FilterDescriptor->CategoriesCount;
+    This->Topology.Categories = FilterDescriptor->Categories;
+    This->Topology.TopologyNodesCount = FilterDescriptor->NodeDescriptorsCount;
+    This->Topology.TopologyConnectionsCount = FilterDescriptor->ConnectionsCount;
+    This->Topology.TopologyConnections = FilterDescriptor->Connections;
+
+    /* are there any templates */
     if (FilterDescriptor->PinDescriptorsCount)
     {
-        /* allocate pin instance count array */
-        This->PinInstanceCount = AllocateItem(NonPagedPool, sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount);
-        if(!This->PinDescriptors)
+        /* sanity check */
+        ASSERT(FilterDescriptor->PinDescriptors);
+
+        /* FIXME handle variable sized pin descriptors */
+        ASSERT(FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
+
+        /* store pin descriptors ex */
+        Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->Filter.Descriptor->PinDescriptors, FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount,
+                         FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount, 0);
+
+        if (!NT_SUCCESS(Status))
         {
-            return STATUS_INSUFFICIENT_RESOURCES;
+            DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
+            return Status;
         }
 
-        /* allocate first pin array */
-        This->FirstPin = AllocateItem(NonPagedPool, sizeof(PKSPIN) * FilterDescriptor->PinDescriptorsCount);
-        if(!This->FirstPin)
+        /* store pin instance count */
+        Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinInstanceCount, sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount,
+                         sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount, 0);
+
+        if (!NT_SUCCESS(Status))
         {
-            FreeItem(This->PinDescriptors);
-            return STATUS_INSUFFICIENT_RESOURCES;
+            DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
+            return Status;
         }
 
+        /* store instantiated pin arrays */
+        Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->FirstPin, sizeof(PKSPIN) * FilterDescriptor->PinDescriptorsCount,
+                         sizeof(PKSPIN) * FilterDescriptor->PinDescriptorsCount, 0);
 
-        /* allocate pin descriptor array */
-        This->PinDescriptors = AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR) * FilterDescriptor->PinDescriptorsCount);
-        if(!This->PinDescriptors)
+        if (!NT_SUCCESS(Status))
         {
-            FreeItem(This->PinInstanceCount);
-            return STATUS_INSUFFICIENT_RESOURCES;
+            DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
+            return Status;
         }
 
-        /* set pin count */
-        This->PinDescriptorCount = FilterDescriptor->PinDescriptorsCount;
-        /* now copy those pin descriptors over */
-        for(Index = 0; Index < FilterDescriptor->PinDescriptorsCount; Index++)
+        /* add new pin factory */
+        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);
+
+        if (!NT_SUCCESS(Status))
         {
-            /* copy one pin per time */
-            RtlMoveMemory(&This->PinDescriptors[Index], &FilterDescriptor->PinDescriptors[Index].PinDescriptor, sizeof(KSPIN_DESCRIPTOR));
+            DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
+            return Status;
         }
+
     }
 
-    /* initialize topology descriptor */
-    This->Topology.CategoriesCount = FilterDescriptor->CategoriesCount;
-    This->Topology.Categories = FilterDescriptor->Categories;
-    This->Topology.TopologyNodesCount = FilterDescriptor->NodeDescriptorsCount;
-    This->Topology.TopologyConnectionsCount = FilterDescriptor->ConnectionsCount;
-    This->Topology.TopologyConnections = FilterDescriptor->Connections;
 
-    if (This->Topology.TopologyNodesCount > 0)
+    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)
     {
-        This->Topology.TopologyNodes = AllocateItem(NonPagedPool, sizeof(GUID) * This->Topology.TopologyNodesCount);
+        /* sanity check */
+        ASSERT(FilterDescriptor->NodeDescriptors);
+
+        /* FIXME handle variable sized node descriptors */
+        ASSERT(FilterDescriptor->NodeDescriptorSize == sizeof(KSNODE_DESCRIPTOR));
+
+        This->Topology.TopologyNodes = AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescriptor->NodeDescriptorsCount);
         /* allocate topology node types array */
         if (!This->Topology.TopologyNodes)
+        {
+            DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
             return STATUS_INSUFFICIENT_RESOURCES;
+        }
 
-        This->Topology.TopologyNodesNames = AllocateItem(NonPagedPool, sizeof(GUID) * This->Topology.TopologyNodesCount);
+        This->Topology.TopologyNodesNames = AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescriptor->NodeDescriptorsCount);
         /* allocate topology names array */
         if (!This->Topology.TopologyNodesNames)
         {
             FreeItem((PVOID)This->Topology.TopologyNodes);
+            DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
             return STATUS_INSUFFICIENT_RESOURCES;
         }
 
-        for(Index = 0; Index < This->Topology.TopologyNodesCount; Index++)
+        DPRINT("NodeDescriptorCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
+        for(Index = 0; Index < FilterDescriptor->NodeDescriptorsCount; Index++)
         {
+            DPRINT("Index %lu Type %p Name %p\n", Index, FilterDescriptor->NodeDescriptors[Index].Type, FilterDescriptor->NodeDescriptors[Index].Name);
+
             /* copy topology type */
-            RtlMoveMemory((PVOID)&This->Topology.TopologyNodes[Index], FilterDescriptor->NodeDescriptors[Index].Type, sizeof(GUID));
+            if (FilterDescriptor->NodeDescriptors[Index].Type)
+                RtlMoveMemory((PVOID)&This->Topology.TopologyNodes[Index], FilterDescriptor->NodeDescriptors[Index].Type, sizeof(GUID));
+
             /* copy topology name */
-            RtlMoveMemory((PVOID)&This->Topology.TopologyNodesNames[Index], FilterDescriptor->NodeDescriptors[Index].Name, sizeof(GUID));
+            if (FilterDescriptor->NodeDescriptors[Index].Name)
+                RtlMoveMemory((PVOID)&This->Topology.TopologyNodesNames[Index], FilterDescriptor->NodeDescriptors[Index].Name, sizeof(GUID));
         }
     }
-
     /* done! */
     return STATUS_SUCCESS;
 }
@@ -861,92 +1233,57 @@ IKsFilter_CopyFilterDescriptor(
     IKsFilterImpl * This,
     const KSFILTER_DESCRIPTOR* FilterDescriptor)
 {
-    This->Filter.Descriptor = (const KSFILTER_DESCRIPTOR*)AllocateItem(NonPagedPool, sizeof(KSFILTER_DESCRIPTOR));
+    NTSTATUS Status;
+    KSAUTOMATION_TABLE AutomationTable;
+
+    This->Filter.Descriptor = AllocateItem(NonPagedPool, sizeof(KSFILTER_DESCRIPTOR));
     if (!This->Filter.Descriptor)
         return STATUS_INSUFFICIENT_RESOURCES;
 
-    /* copy all fields */
-    RtlMoveMemory((PVOID)This->Filter.Descriptor, FilterDescriptor, sizeof(KSFILTER_DESCRIPTOR));
-
-
-    /* perform deep copy of pin descriptors */
-    if (FilterDescriptor->PinDescriptorsCount)
-    {
-        KSPIN_DESCRIPTOR_EX * PinDescriptors = (KSPIN_DESCRIPTOR_EX *)AllocateItem(NonPagedPool, FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount);
-
-
-        if (!PinDescriptors)
-        {
-            FreeItem((PVOID)This->Filter.Descriptor);
-            return STATUS_INSUFFICIENT_RESOURCES;
-        }
-        RtlMoveMemory((PVOID)PinDescriptors, FilterDescriptor->PinDescriptors, FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount);
-
-        /* brain-dead gcc hack */
-        RtlMoveMemory((PVOID)&This->Filter.Descriptor->PinDescriptors, PinDescriptors, sizeof(PKSPIN_DESCRIPTOR_EX));
-
-    }
-
-    /* perform deep copy of node descriptors */
-    if (FilterDescriptor->NodeDescriptorsCount)
+    Status = KsAddItemToObjectBag(This->Filter.Bag, (PVOID)This->Filter.Descriptor, NULL);
+    if (!NT_SUCCESS(Status))
     {
-        KSNODE_DESCRIPTOR* NodeDescriptor = AllocateItem(NonPagedPool, FilterDescriptor->NodeDescriptorsCount * FilterDescriptor->NodeDescriptorSize);
-        if (!NodeDescriptor)
-        {
-            if (This->Filter.Descriptor->PinDescriptors)
-                FreeItem((PVOID)This->Filter.Descriptor->PinDescriptors);
-            FreeItem((PVOID)This->Filter.Descriptor);
-            return STATUS_INSUFFICIENT_RESOURCES;
-        }
-        RtlMoveMemory((PVOID)NodeDescriptor, FilterDescriptor->NodeDescriptors, FilterDescriptor->NodeDescriptorsCount * FilterDescriptor->NodeDescriptorSize);
-
-        /* brain-dead gcc hack */
-        RtlMoveMemory((PVOID)&This->Filter.Descriptor->NodeDescriptors, NodeDescriptor, sizeof(PKSNODE_DESCRIPTOR));
+        FreeItem((PVOID)This->Filter.Descriptor);
+        This->Filter.Descriptor = NULL;
+        return STATUS_INSUFFICIENT_RESOURCES;
     }
 
-    /* perform deep copy of connections descriptors */
-    if (FilterDescriptor->NodeDescriptorsCount)
-    {
-        KSTOPOLOGY_CONNECTION* Connections = AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY_CONNECTION) * FilterDescriptor->ConnectionsCount);
-        if (!Connections)
-        {
-            if (This->Filter.Descriptor->PinDescriptors)
-                FreeItem((PVOID)This->Filter.Descriptor->PinDescriptors);
+    /* copy filter descriptor fields */
+    RtlMoveMemory((PVOID)This->Filter.Descriptor, FilterDescriptor, sizeof(KSFILTER_DESCRIPTOR));
 
-            if (This->Filter.Descriptor->NodeDescriptors)
-                FreeItem((PVOID)This->Filter.Descriptor->PinDescriptors);
+    /* zero automation table */
+    RtlZeroMemory(&AutomationTable, sizeof(KSAUTOMATION_TABLE));
 
-            FreeItem((PVOID)This->Filter.Descriptor);
-            return STATUS_INSUFFICIENT_RESOURCES;
-        }
+    /* setup filter property sets */
+    AutomationTable.PropertyItemSize = sizeof(KSPROPERTY_ITEM);
+    AutomationTable.PropertySetsCount = 2;
+    AutomationTable.PropertySets = FilterPropertySet;
 
-        RtlMoveMemory((PVOID)Connections, FilterDescriptor->Connections, sizeof(KSTOPOLOGY_CONNECTION) * FilterDescriptor->ConnectionsCount);
+    /* merge filter automation table */
+    Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&This->Filter.Descriptor->AutomationTable, (PKSAUTOMATION_TABLE)FilterDescriptor->AutomationTable, &AutomationTable, This->Filter.Bag);
 
-        /* brain-dead gcc hack */
-        RtlMoveMemory((PVOID)&This->Filter.Descriptor->Connections, Connections, sizeof(PKSTOPOLOGY_CONNECTION));
-    }
-
-    return STATUS_SUCCESS;
+    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 */
@@ -968,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);
 }
 
 
@@ -984,48 +1371,61 @@ IKsFilter_DispatchCreatePin(
     PKSPIN_CONNECT Connect;
     NTSTATUS Status;
 
+    DPRINT("IKsFilter_DispatchCreatePin\n");
+
     /* get the create item */
     CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
 
     /* get the filter object */
     This = (IKsFilterImpl*)CreateItem->Context;
 
+    /* sanity check */
+    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->Filter.Descriptor->PinDescriptorsCount);
+
+        DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest PinId %lu CurrentInstanceCount %lu MaxPossible %lu\n", Connect->PinId, 
+               This->PinInstanceCount[Connect->PinId],
+               This->Filter.Descriptor->PinDescriptors[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, (KSPIN_DESCRIPTOR_EX*)&This->Filter.Descriptor->PinDescriptors[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]);
 
-            if (NT_SUCCESS(Status))
-            {
-                /* successfully created pin, increment pin instance count */
-                This->PinInstanceCount[Connect->PinId]++;
-            }
+            DPRINT("IKsFilter_DispatchCreatePin  KspCreatePin %lx\n", Status);
         }
         else
         {
             /* maximum instance count reached, bye-bye */
             Status = STATUS_UNSUCCESSFUL;
+            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 */
+    DPRINT("IKsFilter_DispatchCreatePin Result %lx\n", Status);
     return Status;
 }
 
@@ -1037,7 +1437,7 @@ IKsFilter_DispatchCreateNode(
 {
     UNIMPLEMENTED
     Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    CompleteRequest(Irp, IO_NO_INCREMENT);
     return STATUS_UNSUCCESSFUL;
 }
 
@@ -1084,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(
@@ -1111,44 +1585,64 @@ 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(IKsFilterFactory));
+    This = AllocateItem(NonPagedPool, sizeof(IKsFilterImpl));
     if (!This)
+    {
+        DPRINT1("KspCreateFilter OutOfMemory\n");
         return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* initialize object bag */
+    This->Filter.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
+    if (!This->Filter.Bag)
+    {
+        /* no memory */
+        FreeItem(This);
+        DPRINT1("KspCreateFilter OutOfMemory\n");
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+    KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->BasicHeader.OuterUnknown;
+    KsDevice->lpVtbl->InitializeObjectBag(KsDevice, (PKSIOBJECT_BAG)This->Filter.Bag, NULL);
 
     /* copy filter descriptor */
     Status = IKsFilter_CopyFilterDescriptor(This, Factory->FilterDescriptor);
     if (!NT_SUCCESS(Status))
     {
         /* not enough memory */
+        FreeItem(This->Filter.Bag);
         FreeItem(This);
+        DPRINT("KspCreateFilter IKsFilter_CopyFilterDescriptor failed %lx\n", Status);
         return STATUS_INSUFFICIENT_RESOURCES;
     }
 
     /* get current irp stack */
     IoStack = IoGetCurrentIrpStackLocation(Irp);
 
-    /* initialize object bag */
-    This->Filter.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
-    if (!This->Filter.Bag)
-    {
-        /* no memory */
-        FreeItem(This);
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-
     /* allocate create items */
     CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM) * 2);
     if (!CreateItem)
     {
         /* no memory */
+        FreeItem(This->Filter.Bag);
         FreeItem(This);
+        DPRINT1("KspCreateFilter OutOfMemory\n");
         return STATUS_INSUFFICIENT_RESOURCES;
     }
 
@@ -1164,37 +1658,59 @@ KspCreateFilter(
     RtlInitUnicodeString(&CreateItem[1].ObjectClass, KSSTRING_TopologyNode);
 
 
-    KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->lpVtblIKsDevice;
-    KsDevice->lpVtbl->InitializeObjectBag(KsDevice, (PKSIOBJECT_BAG)This->Filter.Bag, NULL);
-
     /* 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);
         return Status;
     }
 
+
+
     /* does the filter have a filter dispatch */
     if (Factory->FilterDescriptor->Dispatch)
     {
@@ -1202,6 +1718,9 @@ KspCreateFilter(
         if (Factory->FilterDescriptor->Dispatch->Create)
         {
             /* now let driver initialize the filter instance */
+
+            ASSERT(This->Header.KsDevice);
+            ASSERT(This->Header.KsDevice->Started);
             Status = Factory->FilterDescriptor->Dispatch->Create(&This->Filter, Irp);
 
             if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
@@ -1210,6 +1729,7 @@ KspCreateFilter(
                 DPRINT1("Driver: Status %x\n", Status);
 
                 /* free filter instance */
+                KsUnregisterWorker(This->Worker);
                 FreeItem(This);
                 FreeItem(CreateItem);
                 return Status;
@@ -1229,13 +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 */
+    DPRINT1("KspCreateFilter done %lx KsDevice %p\n", Status, This->Header.KsDevice);
     return Status;
 }
 
@@ -1267,6 +1788,7 @@ KsFilterReleaseProcessingMutex(
     KeReleaseMutex(&This->ProcessingMutex, FALSE);
 }
 
+
 /*
     @implemented
 */
@@ -1279,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);
-
-    /* add the new connections */
-    RtlMoveMemory((PVOID)&This->Filter.Descriptor->ConnectionsCount, &Count, sizeof(ULONG)); /* brain-dead gcc hack */
+    /* FIXME verify connections */
 
-    /* free old connections array */
-    if (This->Filter.Descriptor->ConnectionsCount)
-    {
-        FreeItem((PVOID)This->Filter.Descriptor->Connections);
-    }
+    /* copy new connections */
+    RtlMoveMemory((PVOID)&This->Filter.Descriptor->Connections[This->Filter.Descriptor->ConnectionsCount],
+                  NewTopologyConnections,
+                  NewConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION));
 
-    /* brain-dead gcc hack */
-    RtlMoveMemory((PVOID)&This->Filter.Descriptor->Connections, Connections, sizeof(KSTOPOLOGY_CONNECTION*));
+    /* update topology */
+    This->Topology.TopologyConnectionsCount += NewConnectionsCount;
+    ((PKSFILTER_DESCRIPTOR)This->Filter.Descriptor)->ConnectionsCount += NewConnectionsCount;
+    This->Topology.TopologyConnections = This->Filter.Descriptor->Connections;
 
-    return STATUS_SUCCESS;
+    return Status;
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 KSDDKAPI
 VOID
@@ -1325,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);
 }
 
 /*
@@ -1355,84 +1893,65 @@ KsFilterCreatePinFactory (
     OUT PULONG PinID)
 {
     ULONG Count;
-    ULONG *PinInstanceCount;
-    KSPIN_DESCRIPTOR_EX * PinDescriptorsEx;
-    KSPIN_DESCRIPTOR * PinDescriptors;
-    PKSPIN *FirstPin;
+    NTSTATUS Status;
     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
 
-    /* calculate existing count */
-    Count = This->PinDescriptorCount + 1;
+    DPRINT("KsFilterCreatePinFactory\n");
 
-    /* allocate pin descriptors array */
-    PinDescriptorsEx = AllocateItem(NonPagedPool, max(This->Filter.Descriptor->PinDescriptorSize, sizeof(KSPIN_DESCRIPTOR_EX)) * Count);
-    if (!PinDescriptorsEx)
-        return STATUS_INSUFFICIENT_RESOURCES;
+    /* calculate new count */
+    Count = This->Filter.Descriptor->PinDescriptorsCount + 1;
 
-    /* allocate pin instance count array */
-    PinInstanceCount = AllocateItem(NonPagedPool, sizeof(ULONG) * Count);
-    if (!PinInstanceCount)
-    {
-        /* not enough memory */
-        FreeItem(PinDescriptorsEx);
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
+    /* sanity check */
+    ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
 
-    /* allocate pin descriptor array for pin property handling */
-    PinDescriptors = AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR) * Count);
-    if (!PinDescriptors)
+    /* 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))
     {
-        /* not enough memory */
-        FreeItem(PinDescriptorsEx);
-        FreeItem(PinInstanceCount);
-        return STATUS_INSUFFICIENT_RESOURCES;
+        /* failed */
+        DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
+        return Status;
     }
 
-    /* allocate first pin array */
-    FirstPin = AllocateItem(NonPagedPool, sizeof(PKSPIN) * Count);
-    if (!FirstPin)
+    /* 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))
     {
-        /* not enough memory */
-        FreeItem(PinDescriptorsEx);
-        FreeItem(PinInstanceCount);
-        FreeItem(PinDescriptors);
-        return STATUS_INSUFFICIENT_RESOURCES;
+        /* failed */
+        DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
+        return Status;
     }
 
-    /* now copy all fields */
-    if (Count > 1)
+    /* 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))
     {
-        /* copy old descriptors */
-        RtlMoveMemory(PinDescriptorsEx, This->Filter.Descriptor->PinDescriptors, max(This->Filter.Descriptor->PinDescriptorSize, sizeof(KSPIN_DESCRIPTOR_EX)) * This->PinDescriptorCount);
-        RtlMoveMemory(PinInstanceCount, This->PinInstanceCount, This->PinDescriptorCount * sizeof(ULONG));
-        RtlMoveMemory(PinDescriptors, This->PinDescriptors, sizeof(KSPIN_DESCRIPTOR) * This->PinDescriptorCount);
-        RtlMoveMemory(FirstPin, This->FirstPin, sizeof(PKSPIN) * This->PinDescriptorCount);
-
-        /* now free old descriptors */
-        FreeItem(This->PinInstanceCount);
-        FreeItem((PVOID)This->Filter.Descriptor->PinDescriptors);
-        FreeItem(This->PinDescriptors);
-        FreeItem(This->FirstPin);
+        /* failed */
+        DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
+        return Status;
     }
 
     /* add new pin factory */
-    RtlMoveMemory((PVOID)((ULONG_PTR)PinDescriptorsEx + max(This->Filter.Descriptor->PinDescriptorSize, sizeof(KSPIN_DESCRIPTOR_EX)) * This->PinDescriptorCount), InPinDescriptor, sizeof(KSPIN_DESCRIPTOR));
-    RtlMoveMemory((PVOID)(PinDescriptors + This->PinDescriptorCount), &InPinDescriptor->PinDescriptor, sizeof(KSPIN_DESCRIPTOR));
+    RtlMoveMemory((PVOID)&This->Filter.Descriptor->PinDescriptors[This->Filter.Descriptor->PinDescriptorsCount], InPinDescriptor, sizeof(KSPIN_DESCRIPTOR_EX));
 
-    /* replace old descriptor by using a gcc-compliant hack */
-    RtlMoveMemory((PVOID)&This->Filter.Descriptor->PinDescriptors, PinDescriptorsEx, sizeof(KSPIN_DESCRIPTOR_EX*));
-    RtlMoveMemory((PVOID)&This->Filter.Descriptor->PinDescriptorsCount, &Count, sizeof(ULONG));
+    /* allocate process pin index */
+    Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex, sizeof(KSPROCESSPIN_INDEXENTRY) * Count,
+                     sizeof(KSPROCESSPIN_INDEXENTRY) * This->Filter.Descriptor->PinDescriptorsCount, 0);
 
-    This->PinDescriptors = PinDescriptors;
-    This->PinInstanceCount = PinInstanceCount;
-    This->FirstPin = FirstPin;
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT("KsFilterCreatePinFactory _KsEdit failed %lx\n", Status);
+        return Status;
+    }
 
     /* 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");
     return STATUS_SUCCESS;
 
 }
@@ -1446,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;
 }
 
 /*
@@ -1462,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;
@@ -1483,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;
@@ -1522,6 +2043,8 @@ KsGetFilterFromIrp(
     PIO_STACK_LOCATION IoStack;
     PKSIOBJECT_HEADER ObjectHeader;
 
+    DPRINT("KsGetFilterFromIrp\n");
+
     /* get current irp stack location */
     IoStack = IoGetCurrentIrpStackLocation(Irp);