[PORTCLS]
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / undoc.cpp
index bdf32ec..2837123 100644 (file)
@@ -34,13 +34,66 @@ 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
+NTAPI
+PcHandlePropertyWithTable(
+    IN PIRP Irp,
+    IN ULONG PropertySetCount,
+    IN PKSPROPERTY_SET PropertySet,
+    IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor)
+{
+    PIO_STACK_LOCATION IoStack;
+
+    // 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;
+
+    // then try KsPropertyHandler 
+    return KsPropertyHandler(Irp, PropertySetCount, PropertySet);
 }
 
 VOID
@@ -69,16 +122,378 @@ PcAddToEventTable(
     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);
+
+    // 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;
+
+     // 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))
+    {
+        // adjust input buffer size
+        InstanceSize -= sizeof(KSPROPERTY);
+        Instance = (PVOID)((ULONG_PTR)Instance + sizeof(KSPROPERTY));
+
+        // 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);
+
+    // 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));
+
+        for(Index = 0; Index < PropertySet->PropertiesCount; Index++)
+        {
+            // check if they got the same property id
+            if (PropertySet->PropertyItem[Index].PropertyId == Property->Id)
+            {
+                // found item
+                PropertyRequest->PropertyItem = (const PCPROPERTY_ITEM*)PropertySet->PropertyItem[Index].Relations;
+
+                // done
+                break;
+            }
+        }
+    }
+
+    // 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;
+
+            // has it got a automation table
+            if (NodeAutomation)
+            {
+                // now scan the properties and check if it supports this request
+                PropertyItem = (PPCPROPERTY_ITEM)NodeAutomation->Properties;
+                for(Index = 0; Index < NodeAutomation->PropertyCount; Index++)
+                {
+                    // are they same property
+                    if (IsEqualGUIDAligned(*PropertyItem->Set, Property->Set))
+                    {
+                        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 (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);
+        Status = PropertyRequest->PropertyItem->Handler(PropertyRequest);
+
+         Irp->IoStatus.Information = PropertyRequest->ValueSize;
+
+        if (Status != STATUS_PENDING)
+        {
+            // free property request
+            FreeItem(PropertyRequest, TAG_PORTCLASS);
+        }
+    }
+    else
+    {
+        FreeItem(PropertyRequest, TAG_PORTCLASS);
+        Status = STATUS_NOT_FOUND;
+    }
+
+    /* done */
+    return Status;
+}
+
 NTSTATUS
 PcAddToPropertyTable(
-    PVOID Ptr,
-    LONG Unknown,
-    LONG Unknown2,
-    LONG Unknown3,
-    CHAR Unknown4)
+    IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor,
+    IN PPCPROPERTY_ITEM PropertyItem,
+    IN ULONG bNode)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    ULONG bFound = FALSE;
+    ULONG Index, PropertySetIndex, PropertySetItemIndex;
+    PKSPROPERTY_SET NewPropertySet;
+    PKSPROPERTY_ITEM FilterPropertyItem, NewFilterPropertyItem;
+    LPGUID Guid;
+    //UNICODE_STRING GuidBuffer;
+
+ASSERT(PropertyItem->Set);
+       //      RtlStringFromGUID(*PropertyItem->Set, &GuidBuffer);
+   // DPRINT1("PcAddToPropertyTable Adding Item Set %S Id %lu Flags %lx\n", GuidBuffer.Buffer, PropertyItem->Id, PropertyItem->Flags);
+
+
+
+    //DPRINT1("FilterPropertySetCount %lu\n", SubDeviceDescriptor->FilterPropertySetCount);
+    // first step check if the property set is present already
+    for(Index = 0; Index < SubDeviceDescriptor->FilterPropertySetCount; Index++)
+    {
+
+               //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;
+
+            // break out
+            break;
+        }
+    }
+
+    // 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;
+        }
+
+        // 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;
+        }
+
+        // are any existing property sets
+        if (SubDeviceDescriptor->FilterPropertySetCount)
+        {
+            // copy property sets
+            RtlMoveMemory(NewPropertySet, SubDeviceDescriptor->FilterPropertySet, SubDeviceDescriptor->FilterPropertySetCount * sizeof(KSPROPERTY_SET));
+
+            // release memory
+            FreeItem(SubDeviceDescriptor->FilterPropertySet, TAG_PORTCLASS);
+        }
+
+        // store new property set descriptors
+        SubDeviceDescriptor->FilterPropertySet = NewPropertySet;
+
+        // store index 
+        PropertySetIndex = SubDeviceDescriptor->FilterPropertySetCount;
+
+        // increment property set count
+        SubDeviceDescriptor->FilterPropertySetCount++;
+
+        // copy property guid
+        RtlMoveMemory(Guid, PropertyItem->Set, sizeof(GUID));
+
+        // initialize property set 
+        SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].Set = Guid;
+        SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount = 0;
+    }
+
+    // as the property set has been indentified, now search for duplicate property set item entries
+    FilterPropertyItem = (PKSPROPERTY_ITEM)SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem;
+    bFound = FALSE;
+
+    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++;
+    }
+
+    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;
+        }
+
+        // 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));
+
+            // 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
@@ -92,50 +507,105 @@ PcCaptureFormat(
     return STATUS_NOT_IMPLEMENTED;
 }
 
-NTSTATUS
-AddToPropertyTable(
-    IN OUT SUBDEVICE_DESCRIPTOR * Descriptor,
-    IN KSPROPERTY_SET * FilterProperty)
+VOID
+DumpFilterDescriptor(
+    IN PPCFILTER_DESCRIPTOR FilterDescription)
 {
-    if (Descriptor->FilterPropertySet.FreeKsPropertySetOffset >= Descriptor->FilterPropertySet.MaxKsPropertySetCount)
-    {
-        DPRINT1("FIXME\n");
-        return STATUS_UNSUCCESSFUL;
-    }
+    ULONG Index, SubIndex;
+    PPCPROPERTY_ITEM PropertyItem;
+    PPCEVENT_ITEM EventItem;
+    PPCNODE_DESCRIPTOR NodeDescriptor;
+    UNICODE_STRING GuidString;
+
 
-    RtlMoveMemory(&Descriptor->FilterPropertySet.Properties[Descriptor->FilterPropertySet.FreeKsPropertySetOffset],
-                  FilterProperty,
-                  sizeof(KSPROPERTY_SET));
 
-    if (FilterProperty->PropertiesCount)
+    DPRINT("======================\n");
+    DPRINT("Descriptor Automation Table %p\n",FilterDescription->AutomationTable);
+
+    if (FilterDescription->AutomationTable)
     {
-        Descriptor->FilterPropertySet.Properties[Descriptor->FilterPropertySet.FreeKsPropertySetOffset].PropertyItem = (const KSPROPERTY_ITEM*)AllocateItem(NonPagedPool,
-                                                                                                                                    sizeof(KSPROPERTY_ITEM) * FilterProperty->PropertiesCount,
-                                                                                                                                   TAG_PORTCLASS);
+        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;
+
+            for(Index = 0; Index < FilterDescription->AutomationTable->PropertyCount; Index++)
+            {
+                RtlStringFromGUID(*PropertyItem->Set, &GuidString);
+                DPRINT("Property Index %u GUID %S Id %u Flags %x\n", Index, GuidString.Buffer, PropertyItem->Id, PropertyItem->Flags);
 
-        if (!Descriptor->FilterPropertySet.Properties[Descriptor->FilterPropertySet.FreeKsPropertySetOffset].PropertyItem)
+                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++)
         {
-            Descriptor->FilterPropertySet.Properties[Descriptor->FilterPropertySet.FreeKsPropertySetOffset].PropertiesCount = 0;
-            return STATUS_INSUFFICIENT_RESOURCES;
+            DPRINT("Index %u AutomationTable %p\n", Index, NodeDescriptor->AutomationTable);
+
+            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);
         }
-        RtlMoveMemory((PVOID)Descriptor->FilterPropertySet.Properties[Descriptor->FilterPropertySet.FreeKsPropertySetOffset].PropertyItem,
-                      FilterProperty->PropertyItem,
-                      sizeof(KSPROPERTY_ITEM) * FilterProperty->PropertiesCount);
 
-    }
-    Descriptor->FilterPropertySet.Properties[Descriptor->FilterPropertySet.FreeKsPropertySetOffset].Set = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID), TAG_PORTCLASS);
-    if (!Descriptor->FilterPropertySet.Properties[Descriptor->FilterPropertySet.FreeKsPropertySetOffset].Set)
-        return STATUS_INSUFFICIENT_RESOURCES;
 
-    RtlCopyMemory((PVOID)Descriptor->FilterPropertySet.Properties[Descriptor->FilterPropertySet.FreeKsPropertySetOffset].Set, FilterProperty->Set, sizeof(GUID));
 
-    // ignore fast io table for now
-    Descriptor->FilterPropertySet.Properties[Descriptor->FilterPropertySet.FreeKsPropertySetOffset].FastIoCount = 0;
-    Descriptor->FilterPropertySet.Properties[Descriptor->FilterPropertySet.FreeKsPropertySetOffset].FastIoTable = NULL;
+    }
 
-    Descriptor->FilterPropertySet.FreeKsPropertySetOffset++;
+    DPRINT("ConnectionCount: %lu\n", FilterDescription->ConnectionCount);
 
-    return STATUS_SUCCESS;
+    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
@@ -158,9 +628,12 @@ PcCreateSubdeviceDescriptor(
 {
     SUBDEVICE_DESCRIPTOR * Descriptor;
     ULONG Index, SubIndex;
-    PKSDATARANGE DataRange;
     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;
@@ -169,6 +642,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;
@@ -177,110 +651,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
-       Descriptor->FilterPropertySet.Properties = (PKSPROPERTY_SET)AllocateItem(NonPagedPool, sizeof(KSPROPERTY_SET) * FilterPropertiesCount, TAG_PORTCLASS);
-       if (! Descriptor->FilterPropertySet.Properties)
+       // first allocate filter properties set
+       Descriptor->FilterPropertySet = (PKSPROPERTY_SET)AllocateItem(NonPagedPool, sizeof(KSPROPERTY_SET) * FilterPropertiesCount, TAG_PORTCLASS);
+       if (! Descriptor->FilterPropertySet)
            goto cleanup;
 
-       Descriptor->FilterPropertySet.MaxKsPropertySetCount = FilterPropertiesCount;
+       // now copy all filter property sets
+       Descriptor->FilterPropertySetCount = FilterPropertiesCount;
        for(Index = 0; Index < FilterPropertiesCount; Index++)
        {
-           Status = AddToPropertyTable(Descriptor, &FilterProperties[Index]);
-           if (!NT_SUCCESS(Status))
-               goto cleanup;
+           // 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, FilterDescription->PinSize * 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 = FilterDescription->PinSize;
-
-        // copy pin factories
-        for(Index = 0; Index < FilterDescription->PinCount; Index++)
-        {
-            RtlMoveMemory(&Descriptor->Factory.KsPinDescriptor[Index], &FilterDescription->Pins[Index].KsPinDescriptor, FilterDescription->PinSize);
-
-            if (FilterDescription->Pins[Index].KsPinDescriptor.DataRangesCount)
+            // check if has an automation table
+            if (NodeDescriptor->AutomationTable)
             {
-                Descriptor->Factory.KsPinDescriptor[Index].DataRanges = (const PKSDATARANGE*)AllocateItem(NonPagedPool, FilterDescription->Pins[Index].KsPinDescriptor.DataRangesCount * sizeof(PKSDATARANGE), TAG_PORTCLASS);
-                if(!Descriptor->Factory.KsPinDescriptor[Index].DataRanges)
-                    goto cleanup;
+                // grab first entry
+                PropertyItem = (PPCPROPERTY_ITEM)NodeDescriptor->AutomationTable->Properties;
 
-                for (SubIndex = 0; SubIndex < FilterDescription->Pins[Index].KsPinDescriptor.DataRangesCount; SubIndex++)
+                // copy all node properties into the global property set
+                for(SubIndex = 0; SubIndex < NodeDescriptor->AutomationTable->PropertyCount; SubIndex++)
                 {
-                    DataRange = (PKSDATARANGE)AllocateItem(NonPagedPool, FilterDescription->Pins[Index].KsPinDescriptor.DataRanges[SubIndex]->FormatSize, TAG_PORTCLASS);
-                    if (!DataRange)
-                        goto cleanup;
+                    // add to property set
+                    Status = PcAddToPropertyTable(Descriptor, PropertyItem, TRUE);
 
-                    RtlMoveMemory(DataRange,
-                                  FilterDescription->Pins[Index].KsPinDescriptor.DataRanges[SubIndex],
-                                  FilterDescription->Pins[Index].KsPinDescriptor.DataRanges[SubIndex]->FormatSize);
-
-                    ((PKSDATAFORMAT*)Descriptor->Factory.KsPinDescriptor[Index].DataRanges)[SubIndex] = DataRange;
+                    // check for success
+                    if (Status != STATUS_SUCCESS)
+                    {
+                        // failed
+                        goto cleanup;
+                    }
 
+                    // move to next property item
+                    PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + NodeDescriptor->AutomationTable->PropertyItemSize);
                 }
-
-                Descriptor->Factory.KsPinDescriptor[Index].DataRangesCount = FilterDescription->Pins[Index].KsPinDescriptor.DataRangesCount;
             }
 
-            Descriptor->Factory.Instances[Index].CurrentPinInstanceCount = 0;
-            Descriptor->Factory.Instances[Index].MaxFilterInstanceCount = FilterDescription->Pins[Index].MaxFilterInstanceCount;
-            Descriptor->Factory.Instances[Index].MaxGlobalInstanceCount = FilterDescription->Pins[Index].MaxGlobalInstanceCount;
-            Descriptor->Factory.Instances[Index].MinFilterInstanceCount = FilterDescription->Pins[Index].MinFilterInstanceCount;
+            // 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: