[BDASUP]
[reactos.git] / reactos / drivers / multimedia / bdasup / bdasup.c
index a65fe76..221ae83 100644 (file)
@@ -1,6 +1,10 @@
 
 #include "precomp.h"
 
+const GUID KSPROPSETID_BdaPinControl = {0xded49d5, 0xa8b7, 0x4d5d, {0x97, 0xa1, 0x12, 0xb0, 0xc1, 0x95, 0x87, 0x4d}};
+const GUID KSMETHODSETID_BdaDeviceConfiguration = {0x71985f45, 0x1ca1, 0x11d3, {0x9c, 0xc8, 0x0, 0xc0, 0x4f, 0x79, 0x71, 0xe0}};
+const GUID KSPROPSETID_BdaTopology = {0xa14ee835, 0x0a23, 0x11d3, {0x9c, 0xc7, 0x0, 0xc0, 0x4f, 0x79, 0x71, 0xe0}};
+
 BDA_GLOBAL g_Settings =
 {
     0,
@@ -8,6 +12,84 @@ BDA_GLOBAL g_Settings =
     {NULL, NULL}
 };
 
+KSPROPERTY_ITEM FilterPropertyItem[] =
+{
+    DEFINE_KSPROPERTY_ITEM_BDA_NODE_TYPES(BdaPropertyNodeTypes, NULL),
+    DEFINE_KSPROPERTY_ITEM_BDA_PIN_TYPES( BdaPropertyPinTypes, NULL),
+    DEFINE_KSPROPERTY_ITEM_BDA_TEMPLATE_CONNECTIONS(BdaPropertyTemplateConnections, NULL),
+    DEFINE_KSPROPERTY_ITEM_BDA_NODE_METHODS(BdaPropertyNodeMethods, NULL),
+    DEFINE_KSPROPERTY_ITEM_BDA_NODE_PROPERTIES(BdaPropertyNodeProperties, NULL),
+    DEFINE_KSPROPERTY_ITEM_BDA_NODE_EVENTS(BdaPropertyNodeEvents, NULL),
+    DEFINE_KSPROPERTY_ITEM_BDA_CONTROLLING_PIN_ID(BdaPropertyGetControllingPinId, NULL),
+    DEFINE_KSPROPERTY_ITEM_BDA_NODE_DESCRIPTORS(BdaPropertyNodeDescriptors, NULL)
+};
+
+
+KSPROPERTY_SET FilterPropertySet =
+{
+    &KSPROPSETID_BdaTopology,
+    8,
+    FilterPropertyItem,
+    0,
+    NULL
+};
+
+KSMETHOD_ITEM FilterMethodItem[] =
+{
+    //DEFINE_KSMETHOD_ITEM_BDA_CREATE_PIN_FACTORY(BdaMethodCreatePin, NULL),
+    DEFINE_KSMETHOD_ITEM_BDA_CREATE_TOPOLOGY(BdaMethodCreateTopology, NULL)
+};
+
+KSMETHOD_SET FilterMethodSet =
+{
+    &KSMETHODSETID_BdaDeviceConfiguration,
+    2,
+    FilterMethodItem,
+    0,
+    NULL
+};
+
+KSAUTOMATION_TABLE FilterAutomationTable =
+{
+    1,
+    sizeof(KSPROPERTY_ITEM),
+    &FilterPropertySet,
+    1,
+    sizeof(KSMETHOD_ITEM),
+    &FilterMethodSet,
+    0,
+    sizeof(KSEVENT_ITEM),
+    NULL
+};
+
+KSPROPERTY_ITEM PinPropertyItem[] =
+{
+    DEFINE_KSPROPERTY_ITEM_BDA_PIN_ID(BdaPropertyGetPinControl, NULL),
+    DEFINE_KSPROPERTY_ITEM_BDA_PIN_TYPE(BdaPropertyGetPinControl, NULL)
+};
+
+KSPROPERTY_SET PinPropertySet =
+{
+    &KSPROPSETID_BdaPinControl,
+    2,
+    PinPropertyItem,
+    0,
+    NULL
+};
+
+KSAUTOMATION_TABLE PinAutomationTable =
+{
+    1,
+    sizeof(KSPROPERTY_ITEM),
+    &PinPropertySet,
+    0,
+    sizeof(KSMETHOD_ITEM),
+    NULL,
+    0,
+    sizeof(KSEVENT_ITEM),
+    NULL
+};
+
 
 PVOID
 AllocateItem(
@@ -67,6 +149,23 @@ GetFilterInstanceEntry(
     return InstanceEntry;
 }
 
+/*
+    @implemented
+*/
+NTSTATUS
+NTAPI
+DllInitialize(
+    PUNICODE_STRING  RegistryPath)
+{
+    DPRINT("BDASUP::DllInitialize\n");
+
+    KeInitializeSpinLock(&g_Settings.FilterFactoryInstanceListLock);
+    InitializeListHead(&g_Settings.FilterFactoryInstanceList);
+    g_Settings.Initialized = TRUE;
+
+    return STATUS_SUCCESS;
+}
+
 /*
     @implemented
 */
@@ -74,6 +173,8 @@ NTSTATUS
 NTAPI
 BdaCheckChanges(IN PIRP  Irp)
 {
+    DPRINT("BdaCheckChanges\n");
+
     if (!Irp)
         return STATUS_INVALID_PARAMETER;
 
@@ -87,6 +188,8 @@ NTSTATUS
 NTAPI
 BdaCommitChanges(IN PIRP  Irp)
 {
+    DPRINT("BdaCommitChanges\n");
+
     if (!Irp)
         return STATUS_INVALID_PARAMETER;
 
@@ -158,21 +261,42 @@ BdaCreateFilterFactoryEx(
     PBDA_FILTER_INSTANCE_ENTRY FilterInstance;
     KIRQL OldLevel;
     NTSTATUS Status;
+    PKSFILTER_DESCRIPTOR FilterDescriptor;
 
-    /* FIXME provide a default automation table
-     * to handle requests which the driver doesnt implement
-     */
+    DPRINT("BdaCreateFilterFactoryEx\n");
+
+    FilterDescriptor = AllocateItem(NonPagedPool, sizeof(KSFILTER_DESCRIPTOR));
+    if (!FilterDescriptor)
+    {
+        /* no memory */
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* copy filter descriptor template */
+    RtlMoveMemory(FilterDescriptor, pFilterDescriptor, sizeof(KSFILTER_DESCRIPTOR));
+
+    /* merge the automation tables */
+    Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&FilterDescriptor->AutomationTable, (PKSAUTOMATION_TABLE)pFilterDescriptor->AutomationTable, &FilterAutomationTable, NULL);
+
+    /* check for success */
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("KsMergeAutomationTables failed with %lx\n", Status);
+        FreeItem(FilterDescriptor);
+        return Status;
+    }
 
     /* allocate filter instance */
     FilterInstance = AllocateItem(NonPagedPool, sizeof(BDA_FILTER_INSTANCE_ENTRY));
     if (!FilterInstance)
     {
         /* not enough memory */
+        FreeItem(FilterDescriptor);
         return STATUS_INSUFFICIENT_RESOURCES;
     }
 
     /* create the filter factory */
-    Status = KsCreateFilterFactory(pKSDevice->FunctionalDeviceObject, pFilterDescriptor, NULL, NULL, 0, NULL, NULL, &FilterFactory);
+    Status = KsCreateFilterFactory(pKSDevice->FunctionalDeviceObject, FilterDescriptor, NULL, NULL, 0, NULL, NULL, &FilterFactory);
 
     /* check for success */
     if (NT_SUCCESS(Status))
@@ -183,6 +307,8 @@ BdaCreateFilterFactoryEx(
         if (!NT_SUCCESS(Status))
         {
             /* destroy filter instance */
+            DPRINT1("KsAddItemToObjectBag failed with %lx\n", Status);
+            FreeItem(FilterDescriptor);
             FreeItem(FilterInstance);
             KsDeleteFilterFactory(FilterFactory);
             return Status;
@@ -212,9 +338,11 @@ BdaCreateFilterFactoryEx(
     {
         /* failed to create filter factory */
         FreeItem(FilterInstance);
+        DPRINT1("KsCreateFilterFactory failed with %lx\n", Status);
     }
 
     /* done */
+    DPRINT("BdaCreateFilterFactoryEx Status %x\n", Status);
     return Status;
 }
 
@@ -233,15 +361,13 @@ BdaCreatePin(
     PBDA_FILTER_INSTANCE_ENTRY InstanceEntry;
     NTSTATUS Status;
     ULONG PinId;
+    PKSPIN_DESCRIPTOR_EX NewPinDescriptor;
+
+    DPRINT("BdaCreatePin\n");
 
     if (!pulPinId || !pKSFilter)
         return STATUS_INVALID_PARAMETER;
 
-
-    /* FIXME provide a default automation table
-     * to handle requests which the driver doesnt implement
-     */
-
     /* get parent filter factory */
     FilterFactory = KsFilterGetParentFilterFactory(pKSFilter);
 
@@ -265,6 +391,7 @@ BdaCreatePin(
     if (!InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount)
     {
         /* no pins supported */
+        DPRINT("BdaCreatePin NoPins supported\n");
         return STATUS_UNSUCCESSFUL;
     }
 
@@ -272,6 +399,7 @@ BdaCreatePin(
     if (InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount <= ulPinType)
     {
         /* pin request is out of bounds */
+        DPRINT("BdaCreatePin ulPinType %lu >= PinDescriptorCount %lu\n", ulPinType, InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount);
         return STATUS_INVALID_PARAMETER;
     }
 
@@ -281,17 +409,37 @@ BdaCreatePin(
     /* get pin descriptor */
     PinDescriptor = (PKSPIN_DESCRIPTOR_EX)&InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptors[ulPinType];
 
-    /* create the pin factory */
-    Status = KsFilterCreatePinFactory(pKSFilter, PinDescriptor, &PinId);
+    /* allocate pin descriptor */
+    NewPinDescriptor = AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR_EX));
+    if (!NewPinDescriptor)
+    {
+        /* no memory */
+        DPRINT("BdaCreatePin OutOfMemory\n");
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+   /* make a copy of the pin descriptor */
+   RtlMoveMemory(NewPinDescriptor, PinDescriptor, sizeof(KSPIN_DESCRIPTOR_EX));
+
+    /* merge the automation tables */
+    Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&NewPinDescriptor->AutomationTable, (PKSAUTOMATION_TABLE)PinDescriptor->AutomationTable, &PinAutomationTable, pKSFilter->Bag);
 
     /* check for success */
     if (NT_SUCCESS(Status))
     {
-        /* store result */
-        *pulPinId = PinId;
+        /* create the pin factory */
+        Status = KsFilterCreatePinFactory(pKSFilter, NewPinDescriptor, &PinId);
+
+        /* check for success */
+        if (NT_SUCCESS(Status))
+        {
+            /* store result */
+            *pulPinId = PinId;
+        }
     }
 
-    DPRINT("BdaCreatePin Result %x\n", Status);
+
+    DPRINT("BdaCreatePin Result %x PinId %u\n", Status, PinId);
     return Status;
 }
 
@@ -308,6 +456,8 @@ BdaMethodCreatePin(
     PKSM_PIN Pin;
     PKSFILTER Filter;
 
+    DPRINT("BdaMethodCreatePin\n");
+
     if (!Irp)
     {
         /* invalid parameter */
@@ -328,10 +478,8 @@ BdaMethodCreatePin(
     return BdaCreatePin(Filter, Pin->PinId, pulPinFactoryID);
 }
 
-
-
 /*
-    @unimplemented
+    @implemented
 */
 NTSTATUS
 NTAPI
@@ -339,14 +487,54 @@ BdaInitFilter(
     IN PKSFILTER pKSFilter,
     IN const BDA_FILTER_TEMPLATE *pBdaFilterTemplate)
 {
-    UNIMPLEMENTED
-    return STATUS_NOT_IMPLEMENTED;
+    PBDA_FILTER_INSTANCE_ENTRY InstanceEntry;
+    PKSFILTERFACTORY FilterFactory;
+    ULONG Index, PinId;
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    DPRINT("BdaInitFilter %p\n", pBdaFilterTemplate);
+
+    /* check input parameters */
+    if (!pKSFilter)
+        return STATUS_INVALID_PARAMETER;
+
+    /* get parent filter factory */
+    FilterFactory = KsFilterGetParentFilterFactory(pKSFilter);
+
+    /* sanity check */
+    ASSERT(FilterFactory);
+
+    /* find instance entry */
+    InstanceEntry = GetFilterInstanceEntry(FilterFactory);
+
+    /* sanity check */
+    ASSERT(InstanceEntry);
+
+    if (!pBdaFilterTemplate)
+    {
+        /* use template from BdaCreateFilterFactoryEx */
+        pBdaFilterTemplate = InstanceEntry->FilterTemplate;
+    }
+
+    /* now create the pins */
+    for(Index = 0; Index < pBdaFilterTemplate->pFilterDescriptor->PinDescriptorsCount; Index++)
+    {
+        /* create the pin */
+        Status = BdaCreatePin(pKSFilter, Index, &PinId);
+
+        /* check for success */
+        if (!NT_SUCCESS(Status))
+            break;
+    }
+
+    /* done */
+    return Status;
 }
 
 
 
 /*
-    @unimplemented
+    @implemented
 */
 NTSTATUS
 NTAPI
@@ -355,8 +543,46 @@ BdaCreateTopology(
     IN ULONG InputPinId,
     IN ULONG OutputPinId)
 {
-    UNIMPLEMENTED
-    return STATUS_NOT_IMPLEMENTED;
+    PBDA_FILTER_INSTANCE_ENTRY InstanceEntry;
+    PKSFILTERFACTORY FilterFactory;
+    KSTOPOLOGY_CONNECTION Connection;
+
+    DPRINT("BdaCreateTopology\n");
+
+    /* check input parameters */
+    if (!pKSFilter)
+        return STATUS_INVALID_PARAMETER;
+
+    /* get parent filter factory */
+    FilterFactory = KsFilterGetParentFilterFactory(pKSFilter);
+
+    /* sanity check */
+    ASSERT(FilterFactory);
+
+    /* find instance entry */
+    InstanceEntry = GetFilterInstanceEntry(FilterFactory);
+
+    if (!InstanceEntry)
+    {
+        /* the filter was not initialized with BDA */
+        return STATUS_NOT_FOUND;
+    }
+
+    if (InputPinId >= InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount ||
+        OutputPinId >= InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount)
+    {
+        /* invalid pin id */
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* initialize topology connection */
+    Connection.FromNode = KSFILTER_NODE;
+    Connection.ToNode = KSFILTER_NODE;
+    Connection.FromNodePin = InputPinId;
+    Connection.ToNodePin = OutputPinId;
+
+    /* add the connection */
+    return KsFilterAddTopologyConnections(pKSFilter, 1, &Connection);
 }
 
 /*
@@ -369,6 +595,7 @@ BdaDeletePin(
     IN ULONG *pulPinId)
 {
     UNIMPLEMENTED
+    DPRINT("BdaDeletePin\n");
     return STATUS_NOT_IMPLEMENTED;
 }
 
@@ -381,6 +608,7 @@ BdaFilterFactoryUpdateCacheData(
     IN PKSFILTERFACTORY FilterFactory,
     IN const KSFILTER_DESCRIPTOR *FilterDescriptor OPTIONAL)
 {
+    DPRINT("BdaFilterFactoryUpdateCacheData\n");
     return KsFilterFactoryUpdateCacheData(FilterFactory, FilterDescriptor);
 }
 
@@ -393,6 +621,8 @@ BdaGetChangeState(
     IN PIRP Irp,
     OUT BDA_CHANGE_STATE *ChangeState)
 {
+    DPRINT("BdaGetChangeState\n");
+
     if (Irp && ChangeState)
     {
         *ChangeState = BDA_CHANGES_COMPLETE;
@@ -417,6 +647,8 @@ BdaMethodCreateTopology(
     PKSFILTER Filter;
     PKSP_BDA_NODE_PIN Node;
 
+    DPRINT("BdaMethodCreateTopology\n");
+
     /* check input parameters */
     if (!Irp || !pKSMethod)
         return STATUS_INVALID_PARAMETER;
@@ -444,6 +676,8 @@ BdaMethodDeletePin(
     IN KSMETHOD *pKSMethod,
     OPTIONAL PVOID pvIgnored)
 {
+    DPRINT("BdaMethodDeletePin\n");
+
     if (!Irp)
         return STATUS_INVALID_PARAMETER;
 
@@ -461,11 +695,12 @@ BdaPropertyGetControllingPinId(
     OUT ULONG *pulControllingPinId)
 {
     UNIMPLEMENTED
+    DPRINT("BdaPropertyGetControllingPinId\n");
     return STATUS_NOT_IMPLEMENTED;
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 NTSTATUS
 NTAPI
@@ -474,8 +709,37 @@ BdaPropertyGetPinControl(
     IN KSPROPERTY *pKSProperty,
     OUT ULONG *pulProperty)
 {
-    UNIMPLEMENTED
-    return STATUS_NOT_IMPLEMENTED;
+    PKSPIN Pin;
+    PKSFILTER Filter;
+    PKSFILTERFACTORY FilterFactory;
+    PBDA_FILTER_INSTANCE_ENTRY InstanceEntry;
+
+    DPRINT("BdaPropertyGetPinControl\n");
+
+    /* first get the pin */
+    Pin = KsGetPinFromIrp(Irp);
+    ASSERT(Pin);
+
+    /* now get the parent filter */
+    Filter = KsPinGetParentFilter(Pin);
+    ASSERT(Filter);
+
+    /* get parent filter factory */
+    FilterFactory = KsFilterGetParentFilterFactory(Filter);
+    ASSERT(FilterFactory);
+
+    /* find instance entry */
+    InstanceEntry = GetFilterInstanceEntry(FilterFactory);
+    ASSERT(InstanceEntry);
+
+    /* sanity check */
+    pKSProperty++;
+    ASSERT(pKSProperty->Id == KSPROPERTY_BDA_PIN_TYPE);
+
+    /* store pin id */
+    *pulProperty = Pin->Id;
+
+    return STATUS_SUCCESS;
 }
 
 /*
@@ -486,9 +750,10 @@ NTAPI
 BdaPropertyNodeDescriptors(
     IN PIRP Irp,
     IN KSPROPERTY *pKSProperty,
-    OUT GUID *pguidProperty)
+    OUT BDANODE_DESCRIPTOR *pNodeDescriptorProperty)
 {
     UNIMPLEMENTED
+    DPRINT("BdaPropertyNodeDescriptors\n");
     return STATUS_NOT_IMPLEMENTED;
 }
 
@@ -499,10 +764,11 @@ NTSTATUS
 NTAPI
 BdaPropertyNodeEvents(
     IN PIRP Irp,
-    IN KSPROPERTY *pKSProperty,
+    IN KSP_NODE *pKSProperty,
     OUT GUID *pguidProperty)
 {
     UNIMPLEMENTED
+    DPRINT("BdaPropertyNodeEvents\n");
     return STATUS_NOT_IMPLEMENTED;
 }
 
@@ -513,10 +779,11 @@ NTSTATUS
 NTAPI
 BdaPropertyNodeMethods(
     IN PIRP Irp,
-    IN KSPROPERTY *pKSProperty,
+    IN KSP_NODE *pKSProperty,
     OUT GUID *pguidProperty)
 {
     UNIMPLEMENTED
+    DPRINT("BdaPropertyNodeMethods\n");
     return STATUS_NOT_IMPLEMENTED;
 }
 
@@ -527,15 +794,16 @@ NTSTATUS
 NTAPI
 BdaPropertyNodeProperties(
     IN PIRP Irp,
-    IN KSPROPERTY *pKSProperty,
+    IN KSP_NODE *pKSProperty,
     OUT GUID *pguidProperty)
 {
     UNIMPLEMENTED
+    DPRINT("BdaPropertyNodeProperties\n");
     return STATUS_NOT_IMPLEMENTED;
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 NTSTATUS
 NTAPI
@@ -544,12 +812,66 @@ BdaPropertyNodeTypes(
     IN KSPROPERTY *pKSProperty,
     OUT ULONG *pulProperty)
 {
-    UNIMPLEMENTED
-    return STATUS_NOT_IMPLEMENTED;
+    PBDA_FILTER_INSTANCE_ENTRY InstanceEntry;
+    PKSFILTERFACTORY FilterFactory;
+    PKSFILTER pKSFilter;
+    PIO_STACK_LOCATION IoStack;
+    ULONG Index;
+
+    DPRINT("BdaPropertyNodeTypes\n");
+
+    /* check input parameter */
+    if (!Irp || !pKSProperty)
+        return STATUS_INVALID_PARAMETER;
+
+    /* first get the filter */
+    pKSFilter = KsGetFilterFromIrp(Irp);
+
+    /* sanity check */
+    ASSERT(pKSFilter);
+
+    /* get parent filter factory */
+    FilterFactory = KsFilterGetParentFilterFactory(pKSFilter);
+
+    /* sanity check */
+    ASSERT(FilterFactory);
+
+    /* find instance entry */
+    InstanceEntry = GetFilterInstanceEntry(FilterFactory);
+    ASSERT(InstanceEntry);
+
+    /* get current irp stack */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    /* are there node types provided */
+    if (!pulProperty)
+    {
+        /* no node entry array provided */
+        Irp->IoStatus.Information = InstanceEntry->FilterTemplate->pFilterDescriptor->NodeDescriptorsCount * sizeof(ULONG);
+        Irp->IoStatus.Status = STATUS_MORE_ENTRIES;
+        return STATUS_MORE_ENTRIES;
+    }
+
+    if (InstanceEntry->FilterTemplate->pFilterDescriptor->NodeDescriptorsCount * sizeof(ULONG) > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
+    {
+        /* buffer too small */
+        Irp->IoStatus.Information = InstanceEntry->FilterTemplate->pFilterDescriptor->NodeDescriptorsCount * sizeof(ULONG);
+        Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
+        return STATUS_BUFFER_TOO_SMALL;
+    }
+
+    /* now copy all descriptors */
+    for(Index = 0; Index < InstanceEntry->FilterTemplate->pFilterDescriptor->NodeDescriptorsCount; Index++)
+    {
+        /* use the index as the type */
+        pulProperty[Index] = Index;
+    }
+
+    return STATUS_SUCCESS;
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 NTSTATUS
 NTAPI
@@ -558,8 +880,62 @@ BdaPropertyPinTypes(
     IN KSPROPERTY *pKSProperty,
     OUT ULONG *pulProperty)
 {
-    UNIMPLEMENTED
-    return STATUS_NOT_IMPLEMENTED;
+    PBDA_FILTER_INSTANCE_ENTRY InstanceEntry;
+    PKSFILTERFACTORY FilterFactory;
+    PKSFILTER pKSFilter;
+    PIO_STACK_LOCATION IoStack;
+    ULONG Index;
+
+    DPRINT("BdaPropertyPinTypes\n");
+
+    /* check input parameter */
+    if (!Irp || !pKSProperty)
+        return STATUS_INVALID_PARAMETER;
+
+    /* first get the filter */
+    pKSFilter = KsGetFilterFromIrp(Irp);
+
+    /* sanity check */
+    ASSERT(pKSFilter);
+
+    /* get parent filter factory */
+    FilterFactory = KsFilterGetParentFilterFactory(pKSFilter);
+
+    /* sanity check */
+    ASSERT(FilterFactory);
+
+    /* find instance entry */
+    InstanceEntry = GetFilterInstanceEntry(FilterFactory);
+    ASSERT(InstanceEntry);
+
+    /* get current irp stack */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    /* are there node types provided */
+    if (!pKSProperty)
+    {
+        /* no node entry array provided */
+        Irp->IoStatus.Information = InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount * sizeof(ULONG);
+        Irp->IoStatus.Status = STATUS_MORE_ENTRIES;
+        return STATUS_MORE_ENTRIES;
+    }
+
+    if (InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount * sizeof(ULONG) > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
+    {
+        /* buffer too small */
+        Irp->IoStatus.Information = InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount * sizeof(ULONG);
+        Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
+        return STATUS_BUFFER_TOO_SMALL;
+    }
+
+    /* now copy all descriptors */
+    for(Index = 0; Index < InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount; Index++)
+    {
+        /* use the index as the type */
+        pulProperty[Index] = Index;
+    }
+
+    return STATUS_SUCCESS;
 }
 
 /*
@@ -577,6 +953,8 @@ BdaPropertyTemplateConnections(
     PIO_STACK_LOCATION IoStack;
     ULONG Index;
 
+    DPRINT("BdaPropertyTemplateConnections\n");
+
     /* validate parameters */
     if (!Irp || !pKSProperty)
         return STATUS_INVALID_PARAMETER;
@@ -632,6 +1010,8 @@ NTSTATUS
 NTAPI
 BdaStartChanges(IN PIRP Irp)
 {
+    DPRINT("BdaStartChanges\n");
+
     if (Irp)
         return STATUS_SUCCESS;
     else
@@ -646,11 +1026,12 @@ NTSTATUS
 NTAPI
 BdaUninitFilter(IN PKSFILTER pKSFilter)
 {
+    DPRINT("BdaUninitFilter\n");
     return STATUS_SUCCESS;
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 NTSTATUS
 NTAPI
@@ -658,6 +1039,8 @@ BdaValidateNodeProperty(
     IN PIRP Irp,
     IN KSPROPERTY *KSProperty)
 {
+    DPRINT("BdaValidateNodeProperty\n");
+
     /* check for valid parameter */
     if (Irp && KSProperty)
         return STATUS_SUCCESS;