Synchronize with trunk revision 59636 (just before Alex's CreateProcess revamp).
[reactos.git] / drivers / ksfilter / ks / filter.c
index 5f4a74b..384a00c 100644 (file)
@@ -16,6 +16,7 @@ typedef struct
 
     IKsControlVtbl *lpVtblKsControl;
     IKsFilterFactory * FilterFactory;
+    IKsProcessingObjectVtbl * lpVtblKsProcessingObject;
     LONG ref;
 
     PKSIOBJECT_HEADER ObjectHeader;
@@ -25,6 +26,9 @@ typedef struct
     KMUTEX ControlMutex;
     KMUTEX ProcessingMutex;
 
+    PKSWORKER Worker;
+    WORK_QUEUE_ITEM WorkItem;
+    KSGATE Gate;
 
     PFNKSFILTERPOWER Sleep;
     PFNKSFILTERPOWER Wake;
@@ -70,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(
@@ -318,8 +512,8 @@ IKsFilter_fnAddProcessPin(
 
     /* 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),
+                     (This->Filter.Descriptor->PinDescriptorsCount + 1) * sizeof(PVOID),
+                     This->Filter.Descriptor->PinDescriptorsCount * sizeof(PVOID),
                      0);
 
     if (NT_SUCCESS(Status))
@@ -362,7 +556,7 @@ IKsFilter_fnRemoveProcessPin(
     {
         if (Pins[Index] == ProcessPin)
         {
-            RtlMoveMemory(&Pins[Index], &Pins[Index + 1], (Count - (Index + 1)) * sizeof(PKSPROCESSPIN));
+            RtlMoveMemory(&Pins[Index], &Pins[Index + 1], (Count - (Index + 1)) * sizeof(PVOID));
             break;
         }
 
@@ -485,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;
@@ -522,7 +716,7 @@ IKsFilter_DispatchClose(
         /* save the result */
         Irp->IoStatus.Status = Status;
         /* complete irp */
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        CompleteRequest(Irp, IO_NO_INCREMENT);
 
         /* remove our instance from the filter factory */
         IKsFilter_RemoveFilterFromFilterFactory(This, This->Factory);
@@ -535,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 */
@@ -561,7 +755,7 @@ KspHandlePropertyInstances(
     }
 
     /* ignore custom structs for now */
-    ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); 
+    ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
     ASSERT(This->Filter.Descriptor->PinDescriptorsCount > Pin->PinId);
 
     Instances = (KSPIN_CINSTANCES*)Data;
@@ -593,7 +787,7 @@ KspHandleNecessaryPropertyInstances(
     }
 
     /* ignore custom structs for now */
-    ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); 
+    ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
     ASSERT(This->Filter.Descriptor->PinDescriptorsCount > Pin->PinId);
 
     Result = (PULONG)Data;
@@ -641,7 +835,7 @@ KspHandleDataIntersection(
     }
 
     /* ignore custom structs for now */
-    ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); 
+    ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
     ASSERT(This->Filter.Descriptor->PinDescriptorsCount > Pin->PinId);
 
     if (This->Filter.Descriptor->PinDescriptors[Pin->PinId].IntersectHandler == NULL ||
@@ -683,7 +877,7 @@ KspHandleDataIntersection(
             break;
         }
 
-        DataRange =  UlongToPtr(PtrToUlong(DataRange) + DataRange->FormatSize);
+        DataRange = (PKSDATARANGE)((PUCHAR)DataRange + DataRange->FormatSize);
         /* FIXME make sure its 64 bit aligned */
         ASSERT(((ULONG_PTR)DataRange & 0x7) == 0);
     }
@@ -761,7 +955,7 @@ FilterPinPropertyHandler(
             UNIMPLEMENTED
             Status = STATUS_NOT_FOUND;
     }
-    //DPRINT("KspPinPropertyHandler Pins %lu Request->Id %lu Status %lx\n", This->PinDescriptorCount, Request->Id, Status);
+    DPRINT("KspPinPropertyHandler Pins %lu Request->Id %lu Status %lx\n", This->Filter.Descriptor->PinDescriptorsCount, Request->Id, Status);
 
 
     return Status;
@@ -835,6 +1029,9 @@ IKsFilter_DispatchDeviceIoControl(
             SetCount = FilterInstance->Descriptor->AutomationTable->PropertySetsCount;
             PropertySet = FilterInstance->Descriptor->AutomationTable->PropertySets;
             PropertyItemSize = FilterInstance->Descriptor->AutomationTable->PropertyItemSize;
+            // FIXME: handle variable sized property items
+            ASSERT(PropertyItemSize == sizeof(KSPROPERTY_ITEM));
+            PropertyItemSize = 0;
         }
 
         /* needed for our property handlers */
@@ -869,6 +1066,7 @@ IKsFilter_DispatchDeviceIoControl(
     }
 
     RtlStringFromGUID(&Property->Set, &GuidString);
+    DPRINT("IKsFilter_DispatchDeviceIoControl property PinCount %x\n", FilterInstance->Descriptor->PinDescriptorsCount);
     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);
 
@@ -881,7 +1079,7 @@ IKsFilter_DispatchDeviceIoControl(
     if (Status != STATUS_PENDING)
     {
         Irp->IoStatus.Status = Status;
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        CompleteRequest(Irp, IO_NO_INCREMENT);
     }
 
     /* done */
@@ -910,6 +1108,7 @@ IKsFilter_CreateDescriptors(
 {
     ULONG Index = 0;
     NTSTATUS Status;
+    PKSNODE_DESCRIPTOR NodeDescriptor;
 
     /* initialize pin descriptors */
     This->FirstPin = NULL;
@@ -953,8 +1152,8 @@ IKsFilter_CreateDescriptors(
         }
 
         /* store instantiated pin arrays */
-        Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->FirstPin, sizeof(PKSPIN) * FilterDescriptor->PinDescriptorsCount,
-                         sizeof(PKSPIN) * FilterDescriptor->PinDescriptorsCount, 0);
+        Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->FirstPin, sizeof(PVOID) * FilterDescriptor->PinDescriptorsCount,
+                         sizeof(PVOID) * FilterDescriptor->PinDescriptorsCount, 0);
 
         if (!NT_SUCCESS(Status))
         {
@@ -996,8 +1195,8 @@ IKsFilter_CreateDescriptors(
         /* sanity check */
         ASSERT(FilterDescriptor->NodeDescriptors);
 
-        /* FIXME handle variable sized node descriptors */
-        ASSERT(FilterDescriptor->NodeDescriptorSize == sizeof(KSNODE_DESCRIPTOR));
+        /* sanity check */
+        ASSERT(FilterDescriptor->NodeDescriptorSize >= sizeof(KSNODE_DESCRIPTOR));
 
         This->Topology.TopologyNodes = AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescriptor->NodeDescriptorsCount);
         /* allocate topology node types array */
@@ -1017,17 +1216,21 @@ IKsFilter_CreateDescriptors(
         }
 
         DPRINT("NodeDescriptorCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
+        NodeDescriptor = (PKSNODE_DESCRIPTOR)FilterDescriptor->NodeDescriptors;
         for(Index = 0; Index < FilterDescriptor->NodeDescriptorsCount; Index++)
         {
-            DPRINT("Index %lu Type %p Name %p\n", Index, FilterDescriptor->NodeDescriptors[Index].Type, FilterDescriptor->NodeDescriptors[Index].Name);
+            DPRINT("Index %lu Type %p Name %p\n", Index, NodeDescriptor->Type, NodeDescriptor->Name);
 
             /* copy topology type */
-            if (FilterDescriptor->NodeDescriptors[Index].Type)
-                RtlMoveMemory((PVOID)&This->Topology.TopologyNodes[Index], FilterDescriptor->NodeDescriptors[Index].Type, sizeof(GUID));
+            if (NodeDescriptor->Type)
+                RtlMoveMemory((PVOID)&This->Topology.TopologyNodes[Index], NodeDescriptor->Type, sizeof(GUID));
 
             /* copy topology name */
-            if (FilterDescriptor->NodeDescriptors[Index].Name)
-                RtlMoveMemory((PVOID)&This->Topology.TopologyNodesNames[Index], FilterDescriptor->NodeDescriptors[Index].Name, sizeof(GUID));
+            if (NodeDescriptor->Name)
+                RtlMoveMemory((PVOID)&This->Topology.TopologyNodesNames[Index], NodeDescriptor->Name, sizeof(GUID));
+
+            // next node descriptor
+            NodeDescriptor = (PKSNODE_DESCRIPTOR)((ULONG_PTR)NodeDescriptor + FilterDescriptor->NodeDescriptorSize);
         }
     }
     /* done! */
@@ -1201,7 +1404,7 @@ IKsFilter_DispatchCreatePin(
         /* sanity check */
         ASSERT(Connect->PinId < This->Filter.Descriptor->PinDescriptorsCount);
 
-        DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest PinId %lu CurrentInstanceCount %lu MaxPossible %lu\n", Connect->PinId, 
+        DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest PinId %lu CurrentInstanceCount %lu MaxPossible %lu\n", Connect->PinId,
                This->PinInstanceCount[Connect->PinId],
                This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible);
 
@@ -1227,7 +1430,7 @@ IKsFilter_DispatchCreatePin(
     {
         /* complete request */
         Irp->IoStatus.Status = Status;
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        CompleteRequest(Irp, IO_NO_INCREMENT);
     }
 
     /* done */
@@ -1243,7 +1446,7 @@ IKsFilter_DispatchCreateNode(
 {
     UNIMPLEMENTED
     Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    CompleteRequest(Irp, IO_NO_INCREMENT);
     return STATUS_UNSUCCESSFUL;
 }
 
@@ -1356,6 +1559,20 @@ IKsFilter_RemoveFilterFromFilterFactory(
     }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(
@@ -1377,17 +1594,27 @@ KspCreateFilter(
     /* get the filter factory */
     Factory = iface->lpVtbl->GetStruct(iface);
 
-    if (!Factory || !Factory->FilterDescriptor || !Factory->FilterDescriptor->Dispatch || !Factory->FilterDescriptor->Dispatch->Create)
+    if (!Factory || !Factory->FilterDescriptor)
     {
         /* Sorry it just will not work */
         return STATUS_UNSUCCESSFUL;
     }
 
+    if (Factory->FilterDescriptor->Flags & KSFILTER_FLAG_DENY_USERMODE_ACCESS)
+    {
+        if (Irp->RequestorMode == UserMode)
+        {
+            /* filter not accessible from user mode */
+            DPRINT1("Access denied\n");
+            return STATUS_UNSUCCESSFUL;
+        }
+    }
+
     /* allocate filter instance */
     This = AllocateItem(NonPagedPool, sizeof(IKsFilterImpl));
     if (!This)
     {
-        DPRINT("KspCreateFilter OutOfMemory\n");
+        DPRINT1("KspCreateFilter OutOfMemory\n");
         return STATUS_INSUFFICIENT_RESOURCES;
     }
 
@@ -1397,7 +1624,7 @@ KspCreateFilter(
     {
         /* no memory */
         FreeItem(This);
-        DPRINT("KspCreateFilter OutOfMemory\n");
+        DPRINT1("KspCreateFilter OutOfMemory\n");
         return STATUS_INSUFFICIENT_RESOURCES;
     }
     KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->BasicHeader.OuterUnknown;
@@ -1424,12 +1651,10 @@ KspCreateFilter(
         /* no memory */
         FreeItem(This->Filter.Bag);
         FreeItem(This);
-        DPRINT("KspCreateFilter OutOfMemory\n");
+        DPRINT1("KspCreateFilter OutOfMemory\n");
         return STATUS_INSUFFICIENT_RESOURCES;
     }
 
-    DPRINT("KspCreateFilter Flags %lx\n", Factory->FilterDescriptor->Flags);
-
     /* initialize pin create item */
     CreateItem[0].Create = IKsFilter_DispatchCreatePin;
     CreateItem[0].Context = (PVOID)This;
@@ -1446,11 +1671,13 @@ KspCreateFilter(
     This->ref = 1;
     This->Header.OuterUnknown = (PUNKNOWN)&vt_IKsFilter;
     This->lpVtblKsControl = &vt_IKsControl;
+    This->lpVtblKsProcessingObject = &vt_IKsProcessingObject;
 
     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);
@@ -1460,17 +1687,39 @@ KspCreateFilter(
     InitializeListHead(&This->Header.EventList);
     KeInitializeSpinLock(&This->Header.EventListLock);
 
+    /* initialize and gate */
+    KsGateInitializeAnd(&This->Gate, NULL);
+
+    /* FIXME initialize and gate based on pin flags */
+
+    /* initialize work item */
+    ExInitializeWorkItem(&This->WorkItem, IKsFilter_FilterCentricWorker, (PVOID)This->lpVtblKsProcessingObject);
+
+    /* allocate counted work item */
+    Status = KsRegisterCountedWorker(HyperCriticalWorkQueue, &This->WorkItem, &This->Worker);
+    if (!NT_SUCCESS(Status))
+    {
+        /* what can go wrong, goes wrong */
+        DPRINT1("KsRegisterCountedWorker failed with %lx\n", Status);
+        FreeItem(This);
+        FreeItem(CreateItem);
+        return Status;
+    }
+
     /* allocate the stream descriptors */
     Status = IKsFilter_CreateDescriptors(This, (PKSFILTER_DESCRIPTOR)Factory->FilterDescriptor);
     if (!NT_SUCCESS(Status))
     {
         /* what can go wrong, goes wrong */
+        DPRINT1("IKsFilter_CreateDescriptors failed with %lx\n", Status);
+        KsUnregisterWorker(This->Worker);
         FreeItem(This);
         FreeItem(CreateItem);
-        DPRINT("IKsFilter_CreateDescriptors failed with %lx\n", Status);
         return Status;
     }
 
+
+
     /* does the filter have a filter dispatch */
     if (Factory->FilterDescriptor->Dispatch)
     {
@@ -1489,6 +1738,7 @@ KspCreateFilter(
                 DPRINT1("Driver: Status %x\n", Status);
 
                 /* free filter instance */
+                KsUnregisterWorker(This->Worker);
                 FreeItem(This);
                 FreeItem(CreateItem);
                 return Status;
@@ -1515,7 +1765,7 @@ KspCreateFilter(
     IKsFilter_AttachFilterToFilterFactory(This, This->Header.Parent.KsFilterFactory);
 
     /* completed initialization */
-    DPRINT("KspCreateFilter done %lx KsDevice %p\n", Status, This->Header.KsDevice);
+    DPRINT1("KspCreateFilter done %lx KsDevice %p\n", Status, This->Header.KsDevice);
     return Status;
 }
 
@@ -1599,7 +1849,7 @@ KsFilterAddTopologyConnections (
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 KSDDKAPI
 VOID
@@ -1608,7 +1858,20 @@ 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 */
+        return;
+    }
+DPRINT1("processing\n");
+    /* try initiate processing */
+    This->lpVtblKsProcessingObject->Process((IKsProcessingObject*)This->lpVtblKsProcessingObject, Asynchronous);
 }
 
 /*
@@ -1668,7 +1931,7 @@ KsFilterCreatePinFactory (
     }
 
     /* modify first pin array */
-    Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->FirstPin, sizeof(PKSPIN) * Count, sizeof(PKSPIN) * This->Filter.Descriptor->PinDescriptorsCount, 0);
+    Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->FirstPin, sizeof(PVOID) * Count, sizeof(PVOID) * This->Filter.Descriptor->PinDescriptorsCount, 0);
     if (!NT_SUCCESS(Status))
     {
         /* failed */
@@ -1710,8 +1973,10 @@ NTAPI
 KsFilterGetAndGate(
     IN PKSFILTER Filter)
 {
-    UNIMPLEMENTED
-    return NULL;
+    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
+
+    /* return and-gate */
+    return &This->Gate;
 }
 
 /*