[PORTCLS]
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / undoc.cpp
index 56c2597..08970a8 100644 (file)
@@ -8,22 +8,6 @@
 
 #include "private.hpp"
 
-
-KSPIN_INTERFACE PinInterfaces[] = 
-{
-    {
-        {STATIC_KSINTERFACESETID_Standard},
-        KSINTERFACE_STANDARD_STREAMING,
-        0
-    },
-    {
-        {STATIC_KSINTERFACESETID_Standard},
-        KSINTERFACE_STANDARD_LOOPED_STREAMING,
-        0
-    }
-};
-
-
 NTSTATUS
 NTAPI
 KsoDispatchCreateWithGenericFactory(
@@ -50,13 +34,40 @@ NTAPI
 KsoGetIrpTargetFromIrp(
     PIRP Irp)
 {
-    PKSOBJECT_CREATE_ITEM CreateItem;
+    PIO_STACK_LOCATION IoStack;
 
-    // access the create item
-    CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
+    // get current irp stack location
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
 
     // IIrpTarget is stored in Context member
-    return (IIrpTarget*)CreateItem->Context;
+    return (IIrpTarget*)IoStack->FileObject->FsContext;
+}
+
+NTSTATUS
+NTAPI
+PcHandleEnableEventWithTable(
+    IN PIRP Irp,
+    IN PSUBDEVICE_DESCRIPTOR Descriptor)
+{
+    // store descriptor
+    KSEVENT_ITEM_IRP_STORAGE(Irp) = (PKSEVENT_ITEM)Descriptor;
+
+    // FIXME seh probing
+    return KsEnableEvent(Irp, Descriptor->EventSetCount, Descriptor->EventSet, NULL, KSEVENTS_NONE, NULL);
+}
+
+NTSTATUS
+NTAPI
+PcHandleDisableEventWithTable(
+    IN PIRP Irp,
+    IN PSUBDEVICE_DESCRIPTOR Descriptor)
+{
+    // store descriptor
+    KSEVENT_ITEM_IRP_STORAGE(Irp) = (PKSEVENT_ITEM)Descriptor;
+
+    // FIXME seh probing
+
+    return KsDisableEvent(Irp, Descriptor->EventList, KSEVENTS_SPINLOCK, (PVOID)Descriptor->EventListLock);
 }
 
 NTSTATUS
@@ -67,244 +78,425 @@ PcHandlePropertyWithTable(
     IN PKSPROPERTY_SET PropertySet,
     IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor)
 {
-    NTSTATUS Status;
     PIO_STACK_LOCATION IoStack;
-    PKSP_NODE Property;
-    PPCNODE_DESCRIPTOR Node;
-    PPCPROPERTY_ITEM PropertyItem;
-    ULONG Index;
-    LPGUID Buffer;
-    //PULONG Flags;
-    PPCPROPERTY_REQUEST PropertyRequest;
 
+    // get current irp stack location
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY))
+    {
+        // certainly an invalid request
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    // store device descriptor
     KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (PKSPROPERTY_ITEM)SubDeviceDescriptor;
 
-    /* try first KsPropertyHandler */
-    Status = KsPropertyHandler(Irp, PropertySetCount, PropertySet);
+    // then try KsPropertyHandler 
+    return KsPropertyHandler(Irp, PropertySetCount, PropertySet);
+}
 
-    // get current irp stack location
+VOID
+NTAPI
+PcAcquireFormatResources(
+    LONG Unknown,
+    LONG Unknown2,
+    LONG Unknown3,
+    LONG Unknown4)
+{
+    UNIMPLEMENTED;
+}
+
+NTSTATUS
+PcAddToEventTable(
+    PVOID Ptr,
+    LONG Unknown2,
+    ULONG Length,
+    LONG Unknown3,
+    LONG Unknown4,
+    LONG Unknown5,
+    LONG Unknown6,
+    LONG Unknown7)
+{
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+PropertyItemDispatch(
+    IN PIRP Irp,
+    IN PKSIDENTIFIER  Request,
+    IN OUT PVOID  Data)
+{
+    PPCPROPERTY_REQUEST PropertyRequest;
+    PSUBDEVICE_DESCRIPTOR Descriptor;
+    PKSPROPERTY Property;
+    PPCNODE_DESCRIPTOR NodeDescriptor;
+    PKSNODEPROPERTY NodeProperty;
+    PKSPROPERTY_SET PropertySet;
+    PPCPROPERTY_ITEM PropertyItem;
+    PPCAUTOMATION_TABLE NodeAutomation;
+    PIO_STACK_LOCATION IoStack;
+    ULONG InstanceSize, ValueSize, Index;
+    PVOID Instance;
+    NTSTATUS Status;
+
+    // allocate a property request
+    PropertyRequest = (PPCPROPERTY_REQUEST)AllocateItem(NonPagedPool, sizeof(PCPROPERTY_REQUEST), TAG_PORTCLASS);
+    if (!PropertyRequest)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    // grab device descriptor
+    Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
+
+    // get current irp stack
     IoStack = IoGetCurrentIrpStackLocation(Irp);
 
-    // access property
-    Property = (PKSP_NODE)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
+    // get input property request
+    Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
+
+    // get property set
+    PropertySet = (PKSPROPERTY_SET)KSPROPERTY_SET_IRP_STORAGE(Irp);
+
+    // sanity check
+    PC_ASSERT(Descriptor);
+    PC_ASSERT(Descriptor->UnknownMiniport);
+
+    // get instance / value size
+    InstanceSize = IoStack->Parameters.DeviceIoControl.InputBufferLength;
+    Instance = Data;
+    ValueSize = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
 
-    // check if this a GUID_NULL request
-    if (Status == STATUS_NOT_FOUND)
+     // initialize property request
+     PropertyRequest->MajorTarget = Descriptor->UnknownMiniport;
+     PropertyRequest->MinorTarget = Descriptor->UnknownStream;
+     PropertyRequest->Irp = Irp;
+     PropertyRequest->Verb = Property->Flags;
+
+
+    // check if this is filter / pin property request
+    if (!(Property->Flags & KSPROPERTY_TYPE_TOPOLOGY))
     {
-        if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSP_NODE))
-            return Status;
+        // adjust input buffer size
+        InstanceSize -= sizeof(KSPROPERTY);
+        Instance = (PVOID)((ULONG_PTR)Instance + sizeof(KSPROPERTY));
 
-        // check if its a request for a topology node
-        if (IsEqualGUIDAligned(Property->Property.Set, GUID_NULL) && Property->Property.Id == 0 && Property->Property.Flags == (KSPROPERTY_TYPE_SETSUPPORT | KSPROPERTY_TYPE_TOPOLOGY))
-        {
-            if (Property->NodeId >= SubDeviceDescriptor->DeviceDescriptor->NodeCount)
-            {
-                // request is out of bounds
-                Irp->IoStatus.Information = 0;
-                return STATUS_INVALID_PARAMETER;
-            }
+        // filter / pin property request dont use node field
+        PropertyRequest->Node = MAXULONG;
+    }
+    else if (InstanceSize >= sizeof(KSNODEPROPERTY))
+    {
+        // request is for a node
+        InstanceSize -= sizeof(KSNODEPROPERTY);
+        Instance = (PVOID)((ULONG_PTR)Instance + sizeof(KSNODEPROPERTY));
+
+        // cast node property request
+        NodeProperty = (PKSNODEPROPERTY)Request;
+
+        // store node id
+        PropertyRequest->Node = NodeProperty->NodeId;
+    }
+    else
+    {
+        // invalid buffer size
+        return STATUS_INVALID_BUFFER_SIZE;
+    }
+
+    // store instance size
+    PropertyRequest->InstanceSize = InstanceSize;
+    PropertyRequest->Instance = (InstanceSize != 0 ? Instance : NULL);
+
+    // store value size
+    PropertyRequest->ValueSize = ValueSize;
+    PropertyRequest->Value = (ValueSize != 0 ? Irp->UserBuffer : NULL);
 
-            Node = (PPCNODE_DESCRIPTOR)((ULONG_PTR)SubDeviceDescriptor->DeviceDescriptor->Nodes + (Property->NodeId * SubDeviceDescriptor->DeviceDescriptor->NodeSize));
+    // now scan the property set for the attached property set item stored in Relations member
+    if (PropertySet)
+    {
+        // sanity check
+        PC_ASSERT(IsEqualGUIDAligned(Property->Set, *PropertySet->Set));
 
-            if (!Node->AutomationTable)
+        for(Index = 0; Index < PropertySet->PropertiesCount; Index++)
+        {
+            // check if they got the same property id
+            if (PropertySet->PropertyItem[Index].PropertyId == Property->Id)
             {
-                // request is out of bounds
-                Irp->IoStatus.Information = 0;
-                return STATUS_INVALID_PARAMETER;
-            }
+                // found item
+                PropertyRequest->PropertyItem = (const PCPROPERTY_ITEM*)PropertySet->PropertyItem[Index].Relations;
 
-            PC_ASSERT(Node->AutomationTable);
-            PC_ASSERT(Node->AutomationTable->PropertyCount);
-            PC_ASSERT(Node->AutomationTable->PropertyItemSize);
+                // done
+                break;
+            }
+        }
+    }
 
-            Buffer = (LPGUID)AllocateItem(NonPagedPool,  sizeof (GUID) * Node->AutomationTable->PropertyCount, TAG_PORTCLASS);
-             if  (!Buffer)
-                 return  STATUS_INSUFFICIENT_RESOURCES;
+    // check if there has been a property set item attached
+    if (!PropertyRequest->PropertyItem)
+    {
+        // is topology node id valid
+        if (PropertyRequest->Node < Descriptor->DeviceDescriptor->NodeCount)
+        {
+            // get node descriptor
+            NodeDescriptor = (PPCNODE_DESCRIPTOR) ((ULONG_PTR)Descriptor->DeviceDescriptor->Nodes + PropertyRequest->Node * Descriptor->DeviceDescriptor->NodeSize);
 
+            // get node automation table
+            NodeAutomation = (PPCAUTOMATION_TABLE)NodeDescriptor->AutomationTable;
 
-            ULONG Count = 0, SubIndex;
-            PropertyItem = (PCPROPERTY_ITEM*)Node->AutomationTable->Properties;
-            for (Index = 0; Index < Node->AutomationTable->PropertyCount; Index++)
+            // has it got a automation table
+            if (NodeAutomation)
             {
-                BOOL Found = FALSE;
-                for (SubIndex = 0; SubIndex < Count; Index++)
+                // now scan the properties and check if it supports this request
+                PropertyItem = (PPCPROPERTY_ITEM)NodeAutomation->Properties;
+                for(Index = 0; Index < NodeAutomation->PropertyCount; Index++)
                 {
-                    if  (IsEqualGUIDAligned(Buffer[SubIndex], *PropertyItem->Set))
+                    // are they same property
+                    if (IsEqualGUIDAligned(*PropertyItem->Set, Property->Set))
                     {
-                        Found = TRUE;
-                        break;
+                        if (PropertyItem->Id == Property->Id)
+                        {
+                            // found match
+                            PropertyRequest->PropertyItem = PropertyItem;
+
+                            // done
+                            break;
+                        }
                     }
+
+                    // move to next property item
+                    PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + NodeAutomation->PropertyItemSize);
                 }
-                if (!Found)
-                {
-                    RtlMoveMemory(&Buffer[Count], PropertyItem->Set, sizeof (GUID));
-                    Count++;
-                }
-                PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + Node->AutomationTable->PropertyItemSize);
             }
+        }
+    }
 
-            Irp->IoStatus.Information =  sizeof (GUID) * Count;
-            if  (IoStack->Parameters.DeviceIoControl.OutputBufferLength <  sizeof (GUID) * Count)
-            {
-                 // buffer too small
-                 FreeItem(Buffer, TAG_PORTCLASS);
-                 return  STATUS_MORE_ENTRIES;
-            }
+    if (PropertyRequest->PropertyItem && PropertyRequest->PropertyItem->Handler)
+    {
+        // now call the handler
+        UNICODE_STRING GuidBuffer;
+        RtlStringFromGUID(Property->Set, &GuidBuffer);
+        DPRINT1("Calling Node %lu MajorTarget %p MinorTarget %p PropertySet %S PropertyId %lu PropertyFlags %lx InstanceSize %lu ValueSize %lu Handler %p PropertyRequest %p\n",
+                PropertyRequest->Node, PropertyRequest->MajorTarget, PropertyRequest->MinorTarget, GuidBuffer.Buffer, Property->Id, Property->Flags, PropertyRequest->InstanceSize, PropertyRequest->ValueSize,
+                PropertyRequest->PropertyItem->Handler, PropertyRequest);
+#if 0
+        Status = PropertyRequest->PropertyItem->Handler(PropertyRequest);
+#else
+        Status = STATUS_NOT_FOUND;
+#endif
+         Irp->IoStatus.Information = PropertyRequest->ValueSize;
 
-            RtlMoveMemory(Irp->UserBuffer, Buffer,  sizeof (GUID) * Count);
-            FreeItem(Buffer, TAG_PORTCLASS);
-            return STATUS_SUCCESS;
-        }
-        else /*if (Property->Property.Flags == (KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_TOPOLOGY) ||
-                 Property->Property.Flags == (KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_TOPOLOGY) ||
-                 Property->Property.Flags == (KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_TOPOLOGY)) */
+        if (Status != STATUS_PENDING)
         {
-            //UNICODE_STRING GuidString;
+            // free property request
+            FreeItem(PropertyRequest, TAG_PORTCLASS);
+        }
+    }
+    else
+    {
+        FreeItem(PropertyRequest, TAG_PORTCLASS);
+        Status = STATUS_NOT_FOUND;
+    }
 
-            if (Property->NodeId >= SubDeviceDescriptor->DeviceDescriptor->NodeCount)
-            {
-                // request is out of bounds
-                Irp->IoStatus.Information = 0;
-                return STATUS_INVALID_PARAMETER;
-            }
+    /* done */
+    return Status;
+}
 
-            Node = (PPCNODE_DESCRIPTOR)((ULONG_PTR)SubDeviceDescriptor->DeviceDescriptor->Nodes + (Property->NodeId * SubDeviceDescriptor->DeviceDescriptor->NodeSize));
+NTSTATUS
+PcAddToPropertyTable(
+    IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor,
+    IN PPCPROPERTY_ITEM PropertyItem,
+    IN ULONG bNode)
+{
+    ULONG bFound = FALSE;
+    ULONG Index, PropertySetIndex, PropertySetItemIndex;
+    PKSPROPERTY_SET NewPropertySet;
+    PKSPROPERTY_ITEM FilterPropertyItem, NewFilterPropertyItem;
+    LPGUID Guid;
+    //UNICODE_STRING GuidBuffer;
 
-            if (!Node->AutomationTable)
-            {
-                // request is out of bounds
-                Irp->IoStatus.Information = 0;
-                return STATUS_NOT_FOUND;
-            }
+ASSERT(PropertyItem->Set);
+       //      RtlStringFromGUID(*PropertyItem->Set, &GuidBuffer);
+   // DPRINT1("PcAddToPropertyTable Adding Item Set %S Id %lu Flags %lx\n", GuidBuffer.Buffer, PropertyItem->Id, PropertyItem->Flags);
 
-            PC_ASSERT(Node->AutomationTable);
-            PC_ASSERT(Node->AutomationTable->PropertyCount);
-            PC_ASSERT(Node->AutomationTable->PropertyItemSize);
 
-            PropertyItem = (PCPROPERTY_ITEM*)Node->AutomationTable->Properties;
 
-            for(Index = 0; Index < Node->AutomationTable->PropertyCount; Index++)
-            {
-                if (IsEqualGUIDAligned(*PropertyItem->Set, Property->Property.Set) && PropertyItem->Id == Property->Property.Id)
-                {
-                    if (Property->Property.Flags & KSPROPERTY_TYPE_BASICSUPPORT)
-                    {
-                        if (!(PropertyItem->Flags & KSPROPERTY_TYPE_BASICSUPPORT))
-                        {
-                            PC_ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(ULONG));
-                            PULONG Flags = (PULONG)Irp->UserBuffer;
+    //DPRINT1("FilterPropertySetCount %lu\n", SubDeviceDescriptor->FilterPropertySetCount);
+    // first step check if the property set is present already
+    for(Index = 0; Index < SubDeviceDescriptor->FilterPropertySetCount; Index++)
+    {
 
-                            /* reset flags */
-                            *Flags = 0;
+               //RtlStringFromGUID(*SubDeviceDescriptor->FilterPropertySet[Index].Set, &GuidBuffer);
+        //DPRINT1("FilterProperty Set %S PropertyCount %lu\n", GuidBuffer.Buffer, SubDeviceDescriptor->FilterPropertySet[Index].PropertiesCount);
+        if (IsEqualGUIDAligned(*SubDeviceDescriptor->FilterPropertySet[Index].Set, *PropertyItem->Set))
+        {
+            // property set is already present
+            bFound = TRUE;
+            PropertySetIndex = Index;
 
-                            if (PropertyItem->Flags & KSPROPERTY_TYPE_SET)
-                                *Flags |= KSPROPERTY_TYPE_SET;
+            // break out
+            break;
+        }
+    }
 
-                            if (PropertyItem->Flags & KSPROPERTY_TYPE_GET)
-                                *Flags |= KSPROPERTY_TYPE_GET;
+    // is the property set present
+    if (!bFound)
+    {
+        // need to allocate a property set
+        NewPropertySet = (PKSPROPERTY_SET)AllocateItem(NonPagedPool, (SubDeviceDescriptor->FilterPropertySetCount + 1) * sizeof(KSPROPERTY_SET), TAG_PORTCLASS);
+        if (!NewPropertySet)
+        {
+            // out of memory
+            return STATUS_INSUFFICIENT_RESOURCES;
+        }
 
-                            Irp->IoStatus.Information = sizeof(ULONG);
+        // need to allocate property set guid
+        Guid = (LPGUID)AllocateItem(NonPagedPool, sizeof(GUID), TAG_PORTCLASS);
+        if (!Guid)
+        {
+            // out of memory
+            FreeItem(NewPropertySet, TAG_PORTCLASS);
+            return STATUS_INSUFFICIENT_RESOURCES;
+        }
 
-                            if (IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(KSPROPERTY_DESCRIPTION))
-                            {
-                                /* get output buffer */
-                                PKSPROPERTY_DESCRIPTION Description = (PKSPROPERTY_DESCRIPTION)Irp->UserBuffer;
+        // are any existing property sets
+        if (SubDeviceDescriptor->FilterPropertySetCount)
+        {
+            // copy property sets
+            RtlMoveMemory(NewPropertySet, SubDeviceDescriptor->FilterPropertySet, SubDeviceDescriptor->FilterPropertySetCount * sizeof(KSPROPERTY_SET));
 
-                                /* store result */
-                                Description->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION);
-                                Description->PropTypeSet.Set = KSPROPTYPESETID_General;
-                                Description->PropTypeSet.Id = 0;
-                                Description->PropTypeSet.Flags = 0;
-                                Description->MembersListCount = 0;
-                                Description->Reserved = 0;
+            // release memory
+            FreeItem(SubDeviceDescriptor->FilterPropertySet, TAG_PORTCLASS);
+        }
 
-                                Irp->IoStatus.Information = sizeof(KSPROPERTY_DESCRIPTION);
-                            }
-                            return STATUS_SUCCESS;
-                        }
-                    }
+        // store new property set descriptors
+        SubDeviceDescriptor->FilterPropertySet = NewPropertySet;
 
+        // store index 
+        PropertySetIndex = SubDeviceDescriptor->FilterPropertySetCount;
 
-                    PropertyRequest = (PPCPROPERTY_REQUEST)AllocateItem(NonPagedPool, sizeof(PCPROPERTY_REQUEST), TAG_PORTCLASS);
-                    if (!PropertyRequest)
-                        return STATUS_INSUFFICIENT_RESOURCES;
+        // increment property set count
+        SubDeviceDescriptor->FilterPropertySetCount++;
 
-                    PC_ASSERT(SubDeviceDescriptor->UnknownMiniport);
-                    PropertyRequest->MajorTarget = SubDeviceDescriptor->UnknownMiniport;
-                    PropertyRequest->MinorTarget = SubDeviceDescriptor->UnknownStream;
-                    PropertyRequest->Irp = Irp;
-                    PropertyRequest->Node = Property->NodeId;
-                    PropertyRequest->PropertyItem = PropertyItem;
-                    PropertyRequest->Verb = Property->Property.Flags;
-                    PropertyRequest->InstanceSize = IoStack->Parameters.DeviceIoControl.InputBufferLength - sizeof(KSNODEPROPERTY);
-                    PropertyRequest->Instance = (PVOID)((ULONG_PTR)IoStack->Parameters.DeviceIoControl.Type3InputBuffer + sizeof(KSNODEPROPERTY));
-                    PropertyRequest->ValueSize = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
-                    PropertyRequest->Value = Irp->UserBuffer;
+        // copy property guid
+        RtlMoveMemory(Guid, PropertyItem->Set, sizeof(GUID));
 
-                    Status = PropertyItem->Handler(PropertyRequest);
+        // initialize property set 
+        SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].Set = Guid;
+        SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount = 0;
+    }
 
-                    if (Status != STATUS_PENDING)
-                    {
-                        //DPRINT("Status %x ValueSize %u 
+    // as the property set has been indentified, now search for duplicate property set item entries
+    FilterPropertyItem = (PKSPROPERTY_ITEM)SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem;
+    bFound = FALSE;
 
-                        Irp->IoStatus.Information = PropertyRequest->ValueSize;
-                        ExFreePool(PropertyRequest);
-                    }
-#if 0
-                    RtlStringFromGUID(Property->Property.Set, &GuidString);
-                    DPRINT("Id %u Flags %x Set %S FlagsItem %x Status %x\n", Property->Property.Id, Property->Property.Flags, GuidString.Buffer, PropertyItem->Flags, Status);
-                    RtlFreeUnicodeString(&GuidString);
-#endif
-                    return Status;
-                }
-                PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + Node->AutomationTable->PropertyItemSize);
-            }
-#if 0
-            RtlStringFromGUID(Property->Property.Set, &GuidString);
-            DPRINT("Id %u Flags %x Set %S Status %x\n", Property->Property.Id, Property->Property.Flags, GuidString.Buffer, Status);
-            RtlFreeUnicodeString(&GuidString);
-#endif
+    for(Index = 0; Index < SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount; Index++)
+    {
+        // now search for an equal property set item
+        if (FilterPropertyItem->PropertyId == PropertyItem->Id)
+        {
+            // found existing property set item
+            bFound = TRUE;
+            PropertySetItemIndex = Index;
+            break;
         }
+
+        // move to next entry
+        FilterPropertyItem++;
     }
-    return Status;
-}
 
-VOID
-NTAPI
-PcAcquireFormatResources(
-    LONG Unknown,
-    LONG Unknown2,
-    LONG Unknown3,
-    LONG Unknown4)
-{
-    UNIMPLEMENTED;
-}
+    if (!bFound)
+    {
+        // need to allocate memory for new property set item
+        NewFilterPropertyItem = (PKSPROPERTY_ITEM)AllocateItem(NonPagedPool, (SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount + 1) * sizeof(KSPROPERTY_ITEM), TAG_PORTCLASS);
+        if (!NewFilterPropertyItem)
+        {
+            // out of memory
+            return STATUS_INSUFFICIENT_RESOURCES;
+        }
 
-NTSTATUS
-PcAddToEventTable(
-    PVOID Ptr,
-    LONG Unknown2,
-    ULONG Length,
-    LONG Unknown3,
-    LONG Unknown4,
-    LONG Unknown5,
-    LONG Unknown6,
-    LONG Unknown7)
-{
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
-}
+        // are any existing property set items
+        if (SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount)
+        {
+            // copy property item sets
+            RtlMoveMemory(NewFilterPropertyItem,
+                          (PVOID)SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem,
+                          SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount * sizeof(KSPROPERTY_ITEM));
 
-NTSTATUS
-PcAddToPropertyTable(
-    PVOID Ptr,
-    LONG Unknown,
-    LONG Unknown2,
-    LONG Unknown3,
-    CHAR Unknown4)
-{
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+            // release old descriptors
+            FreeItem((PVOID)SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem, TAG_PORTCLASS);
+        }
+
+        // store new descriptor
+        SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem = NewFilterPropertyItem;
+
+        // store index
+        PropertySetItemIndex = SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount;
+
+        // increment property item set count
+        SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount++;
+
+        // now initialize property item
+        FilterPropertyItem = (PKSPROPERTY_ITEM)&SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem[PropertySetItemIndex];
+        FilterPropertyItem->PropertyId = PropertyItem->Id;
+        FilterPropertyItem->MinProperty = sizeof(KSPROPERTY);
+        FilterPropertyItem->MinData = 0;
+
+        // are any set operations supported
+        if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_SET)
+        {
+            // setup handler 
+            FilterPropertyItem->SetPropertyHandler = PropertyItemDispatch;
+        }
+
+        // are set operation supported
+        if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_GET)
+        {
+            // setup handler
+            FilterPropertyItem->GetPropertyHandler = PropertyItemDispatch;
+        }
+
+        // are get operations supported
+        if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_GET)
+        {
+            // setup handler 
+            FilterPropertyItem->GetPropertyHandler = PropertyItemDispatch;
+        }
+
+        // are basic support operations supported
+        if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_BASICSUPPORT)
+        {
+            // setup handler 
+            FilterPropertyItem->SupportHandler = PropertyItemDispatch;
+        }
+
+        if (!bNode)
+        {
+            // store property item in relations
+            // only store property item of filter properties / pin properties
+            // because filter & pin properties do not require a specific context
+            // on the other hand node properties are specifically bound to a node
+             
+            FilterPropertyItem->Relations = (const KSPROPERTY*)PropertyItem;
+        }
+    }
+    else
+    {
+        // property set item handler already present
+
+        if (bNode)
+        {
+            // filter & pin properties should not be exposed on a node
+            ASSERT(SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem[PropertySetItemIndex].Relations == NULL);
+        }
+        else
+        {
+            // node properties should not be exposed on a filter & pin
+            ASSERT(SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem[PropertySetItemIndex].Relations != NULL);
+        }
+    }
+
+    // done
+    return STATUS_SUCCESS;
 }
 
 NTSTATUS
@@ -322,16 +514,21 @@ VOID
 DumpFilterDescriptor(
     IN PPCFILTER_DESCRIPTOR FilterDescription)
 {
-    ULONG Index;
+    ULONG Index, SubIndex;
     PPCPROPERTY_ITEM PropertyItem;
+    PPCEVENT_ITEM EventItem;
+    PPCNODE_DESCRIPTOR NodeDescriptor;
     UNICODE_STRING GuidString;
 
+
+
     DPRINT("======================\n");
-    DPRINT("Descriptor Automation Table%p\n",FilterDescription->AutomationTable);
+    DPRINT("Descriptor Automation Table %p\n",FilterDescription->AutomationTable);
 
     if (FilterDescription->AutomationTable)
     {
-        DPRINT("FilterPropertiesCount %u FilterPropertySize %u Expected %u\n", FilterDescription->AutomationTable->PropertyCount, FilterDescription->AutomationTable->PropertyItemSize, sizeof(PCPROPERTY_ITEM));
+        DPRINT("FilterPropertiesCount %u FilterPropertySize %u Expected %u Events %u EventItemSize %u expected %u\n", FilterDescription->AutomationTable->PropertyCount, FilterDescription->AutomationTable->PropertyItemSize, sizeof(PCPROPERTY_ITEM),
+                FilterDescription->AutomationTable->EventCount, FilterDescription->AutomationTable->EventItemSize, sizeof(PCEVENT_ITEM));
         if (FilterDescription->AutomationTable->PropertyCount)
         {
             PropertyItem = (PPCPROPERTY_ITEM)FilterDescription->AutomationTable->Properties;
@@ -339,15 +536,79 @@ DumpFilterDescriptor(
             for(Index = 0; Index < FilterDescription->AutomationTable->PropertyCount; Index++)
             {
                 RtlStringFromGUID(*PropertyItem->Set, &GuidString);
-                DPRINT("Index %u GUID %S Id %u Flags %x\n", Index, GuidString.Buffer, PropertyItem->Id, PropertyItem->Flags);
+                DPRINT("Property Index %u GUID %S Id %u Flags %x\n", Index, GuidString.Buffer, PropertyItem->Id, PropertyItem->Flags);
 
                 PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + FilterDescription->AutomationTable->PropertyItemSize);
             }
+
+            EventItem = (PPCEVENT_ITEM)FilterDescription->AutomationTable->Events;
+            for(Index = 0; Index < FilterDescription->AutomationTable->EventCount; Index++)
+            {
+                RtlStringFromGUID(*EventItem->Set, &GuidString);
+                DPRINT("EventIndex %u GUID %S Id %u Flags %x\n", Index, GuidString.Buffer, EventItem->Id, EventItem->Flags);
+
+                EventItem = (PPCEVENT_ITEM)((ULONG_PTR)EventItem + FilterDescription->AutomationTable->EventItemSize);
+            }
+
         }
     }
 
+    if (FilterDescription->Nodes)
+    {
+        DPRINT("NodeCount %u NodeSize %u expected %u\n", FilterDescription->NodeCount, FilterDescription->NodeSize, sizeof(PCNODE_DESCRIPTOR));
+        NodeDescriptor = (PPCNODE_DESCRIPTOR)FilterDescription->Nodes;
+        for(Index = 0; Index < FilterDescription->NodeCount; Index++)
+        {
+            DPRINT("Index %u AutomationTable %p\n", Index, NodeDescriptor->AutomationTable);
 
-    DPRINT("======================\n");
+            if (NodeDescriptor->AutomationTable)
+            {
+                DPRINT(" Index %u EventCount %u\n", Index, NodeDescriptor->AutomationTable->EventCount);
+                EventItem = (PPCEVENT_ITEM)NodeDescriptor->AutomationTable->Events;
+                for(SubIndex = 0; SubIndex < NodeDescriptor->AutomationTable->EventCount; SubIndex++)
+                {
+                    RtlStringFromGUID(*EventItem->Set, &GuidString);
+                    DPRINT("  EventIndex %u GUID %S Id %u Flags %x\n", SubIndex, GuidString.Buffer, EventItem->Id, EventItem->Flags);
+
+                    EventItem = (PPCEVENT_ITEM)((ULONG_PTR)EventItem + NodeDescriptor->AutomationTable->EventItemSize);
+                }
+
+                DPRINT1(" Index %u PropertyCount %u\n", Index, NodeDescriptor->AutomationTable->PropertyCount);
+                PropertyItem = (PPCPROPERTY_ITEM)NodeDescriptor->AutomationTable->Properties;
+                for(SubIndex = 0; SubIndex < NodeDescriptor->AutomationTable->PropertyCount; SubIndex++)
+                {
+                    RtlStringFromGUID(*PropertyItem->Set, &GuidString);
+                    DPRINT1("  PropertyIndex %u GUID %S Id %u Flags %x\n", SubIndex, GuidString.Buffer, PropertyItem->Id, PropertyItem->Flags);
+
+                    PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + NodeDescriptor->AutomationTable->PropertyItemSize);
+                }
+            }
+
+
+            NodeDescriptor = (PPCNODE_DESCRIPTOR)((ULONG_PTR)NodeDescriptor + FilterDescription->NodeSize);
+        }
+
+
+
+    }
+
+    DPRINT("ConnectionCount: %lu\n", FilterDescription->ConnectionCount);
+
+    if (FilterDescription->ConnectionCount)
+    {
+        DPRINT("------ Start of Nodes Connections ----------------\n");
+        for(Index = 0; Index < FilterDescription->ConnectionCount; Index++)
+        {
+            DPRINT1("Index %ld FromPin %ld FromNode %ld -> ToPin %ld ToNode %ld\n", Index,
+                                                                                    FilterDescription->Connections[Index].FromNodePin,
+                                                                                    FilterDescription->Connections[Index].FromNode,
+                                                                                    FilterDescription->Connections[Index].ToNodePin,
+                                                                                    FilterDescription->Connections[Index].ToNode);
+        }
+        DPRINT("------ End of Nodes Connections----------------\n");
+    }
+
+    DPRINT1("======================\n");
 }
 
 NTSTATUS
@@ -369,10 +630,13 @@ PcCreateSubdeviceDescriptor(
     IN PPCFILTER_DESCRIPTOR FilterDescription)
 {
     SUBDEVICE_DESCRIPTOR * Descriptor;
-    ULONG Index;
+    ULONG Index, SubIndex;
     NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
     PPCPIN_DESCRIPTOR SrcDescriptor;
+    PPCNODE_DESCRIPTOR NodeDescriptor;
+    PPCPROPERTY_ITEM PropertyItem;
 
+    // allocate subdevice descriptor
     Descriptor = (PSUBDEVICE_DESCRIPTOR)AllocateItem(NonPagedPool, sizeof(SUBDEVICE_DESCRIPTOR), TAG_PORTCLASS);
     if (!Descriptor)
         return STATUS_INSUFFICIENT_RESOURCES;
@@ -381,6 +645,7 @@ PcCreateSubdeviceDescriptor(
     InitializeListHead(&Descriptor->SymbolicLinkList);
     InitializeListHead(&Descriptor->PhysicalConnectionList);
 
+    //FIXME add driver category guids
     Descriptor->Interfaces = (GUID*)AllocateItem(NonPagedPool, sizeof(GUID) * InterfaceCount, TAG_PORTCLASS);
     if (!Descriptor->Interfaces)
         goto cleanup;
@@ -389,98 +654,215 @@ PcCreateSubdeviceDescriptor(
     RtlCopyMemory(Descriptor->Interfaces, InterfaceGuids, sizeof(GUID) * InterfaceCount);
     Descriptor->InterfaceCount = InterfaceCount;
 
+    //DumpFilterDescriptor(FilterDescription);
+
+    // are any property sets supported by the portcls
     if (FilterPropertiesCount)
     {
-       /// FIXME
-       /// handle driver properties
-
-       //DumpFilterDescriptor(FilterDescription);
-
+       // first allocate filter properties set
        Descriptor->FilterPropertySet = (PKSPROPERTY_SET)AllocateItem(NonPagedPool, sizeof(KSPROPERTY_SET) * FilterPropertiesCount, TAG_PORTCLASS);
        if (! Descriptor->FilterPropertySet)
            goto cleanup;
 
+       // now copy all filter property sets
        Descriptor->FilterPropertySetCount = FilterPropertiesCount;
        for(Index = 0; Index < FilterPropertiesCount; Index++)
        {
+           // copy property set
            RtlMoveMemory(&Descriptor->FilterPropertySet[Index], &FilterProperties[Index], sizeof(KSPROPERTY_SET));
+
+           if (Descriptor->FilterPropertySet[Index].PropertiesCount)
+           {
+               // copy property items to make sure they are dynamically allocated
+               Descriptor->FilterPropertySet[Index].PropertyItem = (PKSPROPERTY_ITEM)AllocateItem(NonPagedPool, FilterProperties[Index].PropertiesCount * sizeof(KSPROPERTY_ITEM), TAG_PORTCLASS);
+               if (!Descriptor->FilterPropertySet[Index].PropertyItem)
+               {
+                   // no memory
+                   goto cleanup;
+               }
+
+               // copy filter property items
+               RtlMoveMemory((PVOID)Descriptor->FilterPropertySet[Index].PropertyItem, FilterProperties[Index].PropertyItem, FilterProperties[Index].PropertiesCount * sizeof(KSPROPERTY_ITEM));
+           }
        }
     }
 
+    // now check if the filter descriptor supports filter properties
+    if (FilterDescription->AutomationTable)
+    {
+        // get first entry
+        PropertyItem = (PPCPROPERTY_ITEM)FilterDescription->AutomationTable->Properties;
+
+        // copy driver filter property sets
+        for(Index = 0; Index < FilterDescription->AutomationTable->PropertyCount; Index++)
+        {
+            // add the property item
+            Status = PcAddToPropertyTable(Descriptor, PropertyItem, FALSE);
+
+            // check for success
+            if (Status != STATUS_SUCCESS)
+            {
+                // goto cleanup
+                goto cleanup;
+            }
+
+            // move to next entry
+            PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + FilterDescription->AutomationTable->PropertyItemSize);
+        }
+    }
+
+    // check if the filter has pins
+    if (FilterDescription->PinCount)
+    {
+        // allocate pin factory descriptors
+        Descriptor->Factory.KsPinDescriptor = (PKSPIN_DESCRIPTOR)AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR) * FilterDescription->PinCount, TAG_PORTCLASS);
+        if (!Descriptor->Factory.KsPinDescriptor)
+            goto cleanup;
+
+        // allocate pin instance info
+        Descriptor->Factory.Instances = (PPIN_INSTANCE_INFO)AllocateItem(NonPagedPool, FilterDescription->PinCount * sizeof(PIN_INSTANCE_INFO), TAG_PORTCLASS);
+        if (!Descriptor->Factory.Instances)
+            goto cleanup;
+
+        // initialize pin factory descriptor
+        Descriptor->Factory.PinDescriptorCount = FilterDescription->PinCount;
+        Descriptor->Factory.PinDescriptorSize = sizeof(KSPIN_DESCRIPTOR);
+
+        // grab first entry
+        SrcDescriptor = (PPCPIN_DESCRIPTOR)FilterDescription->Pins;
+
+        // copy pin factories
+        for(Index = 0; Index < FilterDescription->PinCount; Index++)
+        {
+            // copy pin descriptor
+            RtlMoveMemory(&Descriptor->Factory.KsPinDescriptor[Index], &SrcDescriptor->KsPinDescriptor, sizeof(KSPIN_DESCRIPTOR));
+
+            // initialize pin factory instance data
+            Descriptor->Factory.Instances[Index].CurrentPinInstanceCount = 0;
+            Descriptor->Factory.Instances[Index].MaxFilterInstanceCount = SrcDescriptor->MaxFilterInstanceCount;
+            Descriptor->Factory.Instances[Index].MaxGlobalInstanceCount = SrcDescriptor->MaxGlobalInstanceCount;
+            Descriptor->Factory.Instances[Index].MinFilterInstanceCount = SrcDescriptor->MinFilterInstanceCount;
+
+            // check if the descriptor has an automation table
+            if (SrcDescriptor->AutomationTable)
+            {
+                // it has, grab first entry
+                PropertyItem = (PPCPROPERTY_ITEM)SrcDescriptor->AutomationTable->Properties;
+
+                // now add all supported property items
+                for(SubIndex = 0; SubIndex < SrcDescriptor->AutomationTable->PropertyCount; SubIndex++)
+                {
+                    // add the property item to the table
+                    Status = PcAddToPropertyTable(Descriptor, PropertyItem, FALSE);
+
+                    // check for success
+                    if (Status != STATUS_SUCCESS)
+                    {
+                        // goto cleanup
+                        goto cleanup;
+                    }
+
+                    // move to next entry
+                    PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + SrcDescriptor->AutomationTable->PropertyItemSize);
+                }
+            }
+
+            // move to next entry
+            SrcDescriptor = (PPCPIN_DESCRIPTOR)((ULONG_PTR)SrcDescriptor + FilterDescription->PinSize);
+        }
+    }
+
+    // allocate topology descriptor
     Descriptor->Topology = (PKSTOPOLOGY)AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY), TAG_PORTCLASS);
     if (!Descriptor->Topology)
         goto cleanup;
 
+    // are there any connections
     if (FilterDescription->ConnectionCount)
     {
+        // allocate connection descriptor
         Descriptor->Topology->TopologyConnections = (PKSTOPOLOGY_CONNECTION)AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY_CONNECTION) * FilterDescription->ConnectionCount, TAG_PORTCLASS);
         if (!Descriptor->Topology->TopologyConnections)
             goto cleanup;
 
+        // copy connection descriptor
         RtlMoveMemory((PVOID)Descriptor->Topology->TopologyConnections, FilterDescription->Connections, FilterDescription->ConnectionCount * sizeof(PCCONNECTION_DESCRIPTOR));
+
+        // store connection count
         Descriptor->Topology->TopologyConnectionsCount = FilterDescription->ConnectionCount;
     }
 
+    // does the filter have nodes
     if (FilterDescription->NodeCount)
     {
+        // allocate topology node types array
         Descriptor->Topology->TopologyNodes = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS);
         if (!Descriptor->Topology->TopologyNodes)
             goto cleanup;
 
+        // allocate topology node names array
         Descriptor->Topology->TopologyNodesNames = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS);
         if (!Descriptor->Topology->TopologyNodesNames)
             goto cleanup;
 
+        // grab first entry
+       NodeDescriptor = (PPCNODE_DESCRIPTOR)FilterDescription->Nodes;
+
+       // iterate all nodes and copy node types / names and node properties
         for(Index = 0; Index < FilterDescription->NodeCount; Index++)
         {
-            if (FilterDescription->Nodes[Index].Type)
+            // does it have a type
+            if (NodeDescriptor->Type)
             {
-                RtlMoveMemory((PVOID)&Descriptor->Topology->TopologyNodes[Index], FilterDescription->Nodes[Index].Type, sizeof(GUID));
+                // copy node type
+                RtlMoveMemory((PVOID)&Descriptor->Topology->TopologyNodes[Index], NodeDescriptor->Type, sizeof(GUID));
             }
-            if (FilterDescription->Nodes[Index].Name)
+
+            // does it have a node name
+            if (NodeDescriptor->Name)
             {
-                RtlMoveMemory((PVOID)&Descriptor->Topology->TopologyNodesNames[Index], FilterDescription->Nodes[Index].Name, sizeof(GUID));
+                // copy node name
+                RtlMoveMemory((PVOID)&Descriptor->Topology->TopologyNodesNames[Index], NodeDescriptor->Name, sizeof(GUID));
             }
-        }
-        Descriptor->Topology->TopologyNodesCount = FilterDescription->NodeCount;
-    }
-
-    if (FilterDescription->PinCount)
-    {
-        Descriptor->Factory.KsPinDescriptor = (PKSPIN_DESCRIPTOR)AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR) * FilterDescription->PinCount, TAG_PORTCLASS);
-        if (!Descriptor->Factory.KsPinDescriptor)
-            goto cleanup;
-
-        Descriptor->Factory.Instances = (PPIN_INSTANCE_INFO)AllocateItem(NonPagedPool, FilterDescription->PinCount * sizeof(PIN_INSTANCE_INFO), TAG_PORTCLASS);
-        if (!Descriptor->Factory.Instances)
-            goto cleanup;
 
-        Descriptor->Factory.PinDescriptorCount = FilterDescription->PinCount;
-        Descriptor->Factory.PinDescriptorSize = sizeof(KSPIN_DESCRIPTOR);
-
-        SrcDescriptor = (PPCPIN_DESCRIPTOR)FilterDescription->Pins;
-        DPRINT("Size %u Expected %u Ex Size %u\n", FilterDescription->PinSize, sizeof(KSPIN_DESCRIPTOR), sizeof(KSPIN_DESCRIPTOR_EX));
+            // check if has an automation table
+            if (NodeDescriptor->AutomationTable)
+            {
+                // grab first entry
+                PropertyItem = (PPCPROPERTY_ITEM)NodeDescriptor->AutomationTable->Properties;
 
-        // copy pin factories
-        for(Index = 0; Index < FilterDescription->PinCount; Index++)
-        {
-            RtlMoveMemory(&Descriptor->Factory.KsPinDescriptor[Index], &SrcDescriptor->KsPinDescriptor, sizeof(KSPIN_DESCRIPTOR));
+                // copy all node properties into the global property set
+                for(SubIndex = 0; SubIndex < NodeDescriptor->AutomationTable->PropertyCount; SubIndex++)
+                {
+                    // add to property set
+                    Status = PcAddToPropertyTable(Descriptor, PropertyItem, TRUE);
 
-            Descriptor->Factory.KsPinDescriptor[Index].Interfaces = PinInterfaces;
-            Descriptor->Factory.KsPinDescriptor[Index].InterfacesCount = sizeof(PinInterfaces) / sizeof(KSPIN_INTERFACE);
+                    // check for success
+                    if (Status != STATUS_SUCCESS)
+                    {
+                        // failed
+                        goto cleanup;
+                    }
 
-            DPRINT("Index %u DataRangeCount %u\n", Index, SrcDescriptor->KsPinDescriptor.DataRangesCount);
+                    // move to next property item
+                    PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + NodeDescriptor->AutomationTable->PropertyItemSize);
+                }
+            }
 
-            Descriptor->Factory.Instances[Index].CurrentPinInstanceCount = 0;
-            Descriptor->Factory.Instances[Index].MaxFilterInstanceCount = SrcDescriptor->MaxFilterInstanceCount;
-            Descriptor->Factory.Instances[Index].MaxGlobalInstanceCount = SrcDescriptor->MaxGlobalInstanceCount;
-            Descriptor->Factory.Instances[Index].MinFilterInstanceCount = SrcDescriptor->MinFilterInstanceCount;
-            SrcDescriptor = (PPCPIN_DESCRIPTOR)((ULONG_PTR)SrcDescriptor + FilterDescription->PinSize);
+            // move to next descriptor
+            NodeDescriptor = (PPCNODE_DESCRIPTOR)((ULONG_PTR)NodeDescriptor + FilterDescription->NodeSize);
         }
+
+        // now store the topology node count
+        Descriptor->Topology->TopologyNodesCount = FilterDescription->NodeCount;
     }
 
+    // store descriptor
     Descriptor->DeviceDescriptor = FilterDescription;
+
+    // store result
     *OutSubdeviceDescriptor = Descriptor;
+    // done
     return STATUS_SUCCESS;
 
 cleanup: