#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,
{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(
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
*/
NTAPI
BdaCheckChanges(IN PIRP Irp)
{
+ DPRINT("BdaCheckChanges\n");
+
if (!Irp)
return STATUS_INVALID_PARAMETER;
NTAPI
BdaCommitChanges(IN PIRP Irp)
{
+ DPRINT("BdaCommitChanges\n");
+
if (!Irp)
return STATUS_INVALID_PARAMETER;
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))
if (!NT_SUCCESS(Status))
{
/* destroy filter instance */
+ DPRINT1("KsAddItemToObjectBag failed with %lx\n", Status);
+ FreeItem(FilterDescriptor);
FreeItem(FilterInstance);
KsDeleteFilterFactory(FilterFactory);
return Status;
{
/* failed to create filter factory */
FreeItem(FilterInstance);
+ DPRINT1("KsCreateFilterFactory failed with %lx\n", Status);
}
/* done */
+ DPRINT("BdaCreateFilterFactoryEx Status %x\n", Status);
return Status;
}
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);
if (!InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount)
{
/* no pins supported */
+ DPRINT("BdaCreatePin NoPins supported\n");
return STATUS_UNSUCCESSFUL;
}
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;
}
/* 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;
}
PKSM_PIN Pin;
PKSFILTER Filter;
+ DPRINT("BdaMethodCreatePin\n");
+
if (!Irp)
{
/* invalid parameter */
return BdaCreatePin(Filter, Pin->PinId, pulPinFactoryID);
}
-
-
/*
- @unimplemented
+ @implemented
*/
NTSTATUS
NTAPI
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
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);
}
/*
IN ULONG *pulPinId)
{
UNIMPLEMENTED
+ DPRINT("BdaDeletePin\n");
return STATUS_NOT_IMPLEMENTED;
}
IN PKSFILTERFACTORY FilterFactory,
IN const KSFILTER_DESCRIPTOR *FilterDescriptor OPTIONAL)
{
+ DPRINT("BdaFilterFactoryUpdateCacheData\n");
return KsFilterFactoryUpdateCacheData(FilterFactory, FilterDescriptor);
}
IN PIRP Irp,
OUT BDA_CHANGE_STATE *ChangeState)
{
+ DPRINT("BdaGetChangeState\n");
+
if (Irp && ChangeState)
{
*ChangeState = BDA_CHANGES_COMPLETE;
PKSFILTER Filter;
PKSP_BDA_NODE_PIN Node;
+ DPRINT("BdaMethodCreateTopology\n");
+
/* check input parameters */
if (!Irp || !pKSMethod)
return STATUS_INVALID_PARAMETER;
IN KSMETHOD *pKSMethod,
OPTIONAL PVOID pvIgnored)
{
+ DPRINT("BdaMethodDeletePin\n");
+
if (!Irp)
return STATUS_INVALID_PARAMETER;
OUT ULONG *pulControllingPinId)
{
UNIMPLEMENTED
+ DPRINT("BdaPropertyGetControllingPinId\n");
return STATUS_NOT_IMPLEMENTED;
}
/*
- @unimplemented
+ @implemented
*/
NTSTATUS
NTAPI
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;
}
/*
BdaPropertyNodeDescriptors(
IN PIRP Irp,
IN KSPROPERTY *pKSProperty,
- OUT GUID *pguidProperty)
+ OUT BDANODE_DESCRIPTOR *pNodeDescriptorProperty)
{
UNIMPLEMENTED
+ DPRINT("BdaPropertyNodeDescriptors\n");
return STATUS_NOT_IMPLEMENTED;
}
NTAPI
BdaPropertyNodeEvents(
IN PIRP Irp,
- IN KSPROPERTY *pKSProperty,
+ IN KSP_NODE *pKSProperty,
OUT GUID *pguidProperty)
{
UNIMPLEMENTED
+ DPRINT("BdaPropertyNodeEvents\n");
return STATUS_NOT_IMPLEMENTED;
}
NTAPI
BdaPropertyNodeMethods(
IN PIRP Irp,
- IN KSPROPERTY *pKSProperty,
+ IN KSP_NODE *pKSProperty,
OUT GUID *pguidProperty)
{
UNIMPLEMENTED
+ DPRINT("BdaPropertyNodeMethods\n");
return STATUS_NOT_IMPLEMENTED;
}
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
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
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;
}
/*
PIO_STACK_LOCATION IoStack;
ULONG Index;
+ DPRINT("BdaPropertyTemplateConnections\n");
+
/* validate parameters */
if (!Irp || !pKSProperty)
return STATUS_INVALID_PARAMETER;
NTAPI
BdaStartChanges(IN PIRP Irp)
{
+ DPRINT("BdaStartChanges\n");
+
if (Irp)
return STATUS_SUCCESS;
else
NTAPI
BdaUninitFilter(IN PKSFILTER pKSFilter)
{
+ DPRINT("BdaUninitFilter\n");
return STATUS_SUCCESS;
}
/*
- @unimplemented
+ @implemented
*/
NTSTATUS
NTAPI
IN PIRP Irp,
IN KSPROPERTY *KSProperty)
{
+ DPRINT("BdaValidateNodeProperty\n");
+
/* check for valid parameter */
if (Irp && KSProperty)
return STATUS_SUCCESS;